今天看到了一個比較特別的面試題,考察的是如何改變int的System.out.PRint的結果。題目如下:
下面的一句話“這是初級java實習生面試題”非常挑釁的激起了大家做題的欲望。
解題的思路無外乎是3種方法: 1.作弊大法,因為一些面試題總是會出其不意,面對扯淡的問題就要用扯淡的方法。 2.反射,感覺反射是一種比較“高端”用法,因為很多中間件與框架都是通過反射實現的。 3.數據流。反射的思路是修改對應內存上的內容,當無法修改響應內存的時候就要找其他思路了。這里對應的問題就是,System.out.println是如何打印的。
反射的方法我一直沒有成功,這里提供幾個思路
修改緩存池 因為Integer內部維護了一個IntegerCache內部類,其內部維護了一個Integer[]數組來維護從-128到127的Integer對象。private static void method(int a, int b) throws Exception { Class<?> clzz = Integer.class.getDeclaredClasses()[0]; Field field = clzz.getDeclaredField("cache"); field.setaccessible(true); Integer[] cache = (Integer[]) field.get(clzz); cache[138]=100; cache[148]=200;}這樣就修改了緩存區的內容,但是依然沒有完成題目的要求,打印內容沒有改變,因為這樣改變了所有的Integer緩存區對象,但是當前打印的是int。這種情況下,其他的場景倒是可以改變了。
Integer c =10;System.out.println(c);System.out.println(Integer.valueOf(10));修改對象本身private static void method(int a, int b) throws Exception { Field value = Integer.class.getDeclaredField("value"); value.setAccessible(true); value.set(10,100);}效果等于同修改緩存池的方法
了解一點System.out的同學應該很清楚這是通過PringStream流實現的。當然我不是很了解,我是通過反編譯看字節碼發現的。 測試代碼:
public class A { public static void main(String[] args) { int a = 9; System.out.println(a); }}查看字節碼:
發現實際在輸出屏幕的時候調用的是PrintStream對象的println方法實現的,我們可以通過重寫這個方法打印任何內容。
這種方法比較low,屬于手動替換的。下面的方法性質相同,不過看上去高端一點。
間接替換法 private static void method(int a, int b) throws Exception { PrintStream printStream = new PrintStream(System.out) { @Override public void print(String s) { s = s.replace(a + "", a * 10 + "").replace(b + "", b * 10 + ""); super.print(s); } }; System.setOut(printStream);}不知道這個面試題的正確答案是什么,這里提供了兩種方法解決。很可惜反射沒有搞定這個題目,如果哪位同學有更好的方法請留言。
新聞熱點
疑難解答