如何修改int的打印内容——史上最难的JAVA面试题
来源:互联网 发布:淘宝店铺怎么商品分类 编辑:程序博客网 时间:2024/06/06 20:52
序
今天看到了一个比较特别的面试题,考察的是如何改变int的System.out.print的结果。题目如下:
下面的一句话“这是初级java实习生面试题”非常挑衅的激起了大家做题的欲望。
解题思路
解题的思路无外乎是3种方法:
1.作弊大法,因为一些面试题总是会出其不意,面对扯淡的问题就要用扯淡的方法。
2.反射,感觉反射是一种比较“高端”用法,因为很多中间件与框架都是通过反射实现的。
3.数据流。反射的思路是修改对应内存上的内容,当无法修改响应内存的时候就要找其他思路了。这里对应的问题就是,System.out.println是如何打印的。
解题方案
作弊大法
- System.exit
这种方法通过退出jvm线程来终止后面的程序运行,看完之后让人比较崩溃,因为业务中遇到 System.exit的场景比较少。
private static void method(int a, int b) { System.out.println("a=100"); System.out.println("b=200"); System.exit(0); }
- 异常
上面的方法是线程优雅的自己退出JVM,通过异常就是强制使JVM中介当前线程了。
private static void method(int a, int b) { System.out.println("a=100"); System.out.println("b=200"); throw new RuntimeException(); }
反射
反射的方法我一直没有成功,这里提供几个思路
- 修改缓存池
因为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方法实现的,我们可以通过重写这个方法打印任何内容。
- 直接替换法
private static void method(int a, int b) throws Exception { PrintStream printStream = new PrintStream(System.out) { @Override public void print(String s) { if (s.equals("a=10")) { super.print("a=100"); } else if (s.equals("b=20")) { super.print("b=200"); } else super.print(s); } }; System.setOut(printStream);}
这种方法比较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);}
结论
不知道这个面试题的正确答案是什么,这里提供了两种方法解决。很可惜反射没有搞定这个题目,如果哪位同学有更好的方法请留言。
1 0
- 如何修改int的打印内容——史上最难的JAVA面试题
- 盛大游戏面试题----如何修改int类型的第二个字节
- 剑指Offer:面试题12——打印1到最大的n位数(java实现)
- java 关于int和Integer的面试题
- java笔试面试题--int数组的默认值
- 顺序打印ABC------java多线程的一道经典面试题
- J2EE面试题之 java如何找出一个int数组中出现次数最多的数字以及出现次数?
- 面试题-Integer和int的区别
- 剑指offer编程题Java实现——面试题12打印1到最大的n位数
- Java-Integer-int面试题
- java的面试题
- Java面试题-朋友的面试题
- 面试题4——求一个int型整数的两种递减数之和
- 一道打印M型的面试题
- 【面试题】打印“圣诞节的12天”
- 一道打印M的面试题
- 如何打印Java异常的完整堆栈内容
- 【C面试】一道简单的C语言面试题的思考——打印星阵
- 希尔排序
- Blockchain的鱼和熊掌系列(二)分叉问题
- volatile与synchronized的区别
- 基本数据类型转换
- const , volatile 关键字分析
- 如何修改int的打印内容——史上最难的JAVA面试题
- 推荐系统 Lenskit 初探(一)
- IO流_FileOutputStream的构造方法
- RAID扫盲篇之RAID的由来
- Spark经典案例2-数据去重
- Java 的10个谎言
- 最近看的一个小算法
- 静态广播、动态广播以及黏性广播的无序显示
- Hibernate笔记:JAR包导入,常用API,多对一配置