未曾探索过的string连接符"+"
来源:互联网 发布:java实训日志 编辑:程序博客网 时间:2024/06/13 17:18
未曾探索过的string连接符”+”
1.来来来,有个string的面试题想找你谈谈,废话不多说,上菜!!
public class Test{ String a = "abc"; String b = "a" + a;}
这里创建了几个对象(常量池里面的对象也算)
最直观的办法还是看源码!这个怎么搞,不用怕,我们去分析编译过的class文件。这里需要用到javap命令
javac Test.javajavap -c Test
我们会得到如下内容
public static void main(java.lang.String[]); Code: //ldc(loadConstant) 将常量池中的"abc"放入栈顶 0: ldc #2 // String abc //将常量池中"abc"的引用存到第一个局部变量a中 2: astore_1 //新建一个StringBuilder的对象 3: new #3 // class java/lang/StringBuilder //复制栈顶的内容 6: dup //调用StringBuilder构造器 7: invokespecial #4 // Method java/lang/StringBuilder."<init>":()V //将常量池中的"a"放入栈顶 10: ldc #5 // String a //调用stringBuilder的append方法 12: invokevirtual #6 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; //装载第一个局部变量a的值 15: aload_1 //调用stringBuilder的append方法 16: invokevirtual #6 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; //将append的值变为string 19: invokevirtual #7 // Method java/lang/StringBuilder.toString:()Ljava/lang/String; //将生成的string的引用存到第二个局部变量b中 22: astore_2 23: return}
可以看到创建的对象:
在常量池中存在 “abc” 和”a” 两个对象
在堆中创建了StringBuilder对象 ,最后调用toString方法产生一个String对象,里面存”aabc”
答案出来了。这里产生了4个对象。
2.现在再来看两句熟悉的代码
String a = "a";System.out.println(1+2+a); //Q1System.out.println(a+1+2); //Q2
分析:
Q1的输出? “12a” 还是 “3a”
Q2的输出? “a12” 还是”a3”
其实这个题目对比起来看很容易明白,机智的你应该已经发现了端倪。编译器会优先做 “+”运算,当”+”连接的是整形时,先做加法运算,如果连接的是字符串,那么便是字符连接了。所以Q1的结果是”3a”,Q2是”a12”
3.第三个问题来了
String a = null ;Integer b = null;System.out.println(a); //Q1 "null"System.out.println(a + 2); //Q2 "null2"System.out.println(b + 2);//Q3 异常
分析:
Q1是个选择题,选项有空字符串、null、抛异常,当时我就懵逼了。后来去看了源码,Q1代码会直接去找
public void println(String x) { synchronized (this) { print(x); newLine(); }}然后public void print(String s) { if (s == null) { s = "null"; } write(s);}
好的,找到答案了!是”null”
那么Q2呢,Q2执行也会去找println(String x)这个方法,但是此时x已经是”null2”了,所以下面的if判断不会执行的,那么什么时候x变成了”null2”呢?
此时继续查看,会找到一个String.valueOf(Object)的静态方法。到这里大boss出来了,打断点你会发现,不管你执行什么代码,都会走这个方法,这里是是一个反射的源头,是通过这个,最后确定对象的类型,以及返回值。所以”a+2”先确认了返回字符串,然后再去拼接,看class文件你会看到括号里面的内容是(“”+object+2) 。
所以结果出来了,同理Q3也是先确认了返回的括号里面的类型是int,然后做加法运算,括号里面的内容是(((Integer)b).intValue() + 2),但是b对象是空,,所以抛出了null指针异常
另附上一些能帮助理解String的面试题
http://blog.csdn.net/chj97/article/details/6899598
- 未曾探索过的string连接符"+"
- 未曾想过的改变
- mysql解决自动断开8小时未曾用过的连接
- 你未曾了解过的javascript?!!
- 未曾见过这片海
- 未曾注意过的scanf函数的返回值
- 【转】mysql解决自动断开8小时未曾用过的链接
- mysql解决自动断开8小时未曾用过的链接
- mysql解决自动断开8小时未曾用过的链接
- 你未曾见过的移动端下拉列表替代方案
- 未曾遗忘的凝视
- 未曾遗忘的梦想
- 好文转载--从来未曾遗忘过
- 16年扮演同一个角色,未曾换过,而在16年后的某一天却直接切换。
- deblock 未曾想到的痛苦
- String探索
- 那些逝去的那些未曾逝去的
- 未曾被Moblin v2遗忘的Nettop
- LeetCode 1---Tow Sum
- poj_1487 Single-Player Games(高斯消元+自由元)
- 经典算法(3):动态时间规整算法(DTW)
- 编程修养
- qt5串口简易操作
- 未曾探索过的string连接符"+"
- hdu 1717 小数化分数2
- TensorFlow Python API解析:图的核心数据结构
- 解决-Dmaven.multiModuleProjectDirectory system property is not set. Check $M2_HOME environment variabl
- java停止线程的几种方式
- 【leetcode】【Medium】【338. Counting Bits】【规律】
- 今天开始认真学习~明天计划
- Hibernate入门案例
- Android开发——菜单ActionBar