1.引言:不得不说,真的是实践出真知,动手试试比看别人说一万句强。
2. 以前一直看别人的面试题,经常会出现各种
s1 == s2
的问题,今天刚巧看到个文章就自己看了一下String的源码。
3. 咱们从源码层面分析一下 s1 == s2
的问题。
4. 先上一下测试代码和结果:
String a1 = new String("aa");
String a2 = String.valueOf(a1);
String a3 = String.valueOf("aa");
String a4 = String.valueOf(a3);
System.out.println(a1 == a2); // true
System.out.println(a1 == a3); // false
System.out.println(a2 == a3); // false
System.out.println(a3 == a4); // true
- 上一下 String的部分源码,value 是核心
// String的两个属性,value 是核心
private final char value[];
private int hash;
// new String()的源码
public String(String original) {
this.value = original.value;
this.hash = original.hash;
}
// String.valueOf()的源码
public static String valueOf(Object obj) {
return (obj == null) ? "null" : obj.toString();
}
// String的toString()源码
public String toString() {
return this;
}
- 看到 new String()的源码大家能看出来这是一个新的对象;而String.valueOf()的源码 中有一个obj.toString(),众所周知Object是一切的父类,但是实际调用时会优先使用子类重写的toString方法,因此还是会调用String的toString()。
结论:
- String的toString() 是return的this,而"“会创建新的String对象,String.valueOf(”")方法会把新的String对象的地址给返回,两个不一样的对象的地址必然是一样的
- String的字符串数据用的是 private final char value[]; 这是常量,并且每一个"“都会创建一个字符串对象,这种写死的”“字符串常量是不会被回收的,因此需要避免过多的”"字符串常量
- jvm可以卸载动态生成的常量,但是对于写死的常量是不会卸载的,并且也始终会被调用到····
- 以上就是 s1==s2问题的真相了,知道源码原理后突然感觉这个真的很简单,还是需要多去看多实践呀。共勉。