Java中String类型的==运算符行为疑惑及代码问题解析
理解Java中==运算符对String的行为
测试代码
String name = "Object Oriented"; String str1 = "Object"; String str2 = "Object"; String str3 = new String("Object"); String str4 = name.substring(0,6); String str5 = name.substring(0,6); String str6 = "Obj" + "ect"; System.out.println(str1 + "==" + str2 + ": " + (str1 == str2)); System.out.println(str1 + "==" + "Object" + ": " + (str1 == "Object")); System.out.println(str1 + "==" + str6 + ": " + (str1 == str6)); System.out.println(str1 + "==" + str3 + ": " + (str1 == str3)); System.out.println(str1 + "==" + str4 + ": " + (str1 == str4)); System.out.println(str4 + "==" + str5 + ": " + (str4 == str5));
运行输出
Object==Object: true Object==Object: true Object==Object: true Object==Object: false Object==Object: false Object==Object: false
参考资料
为节省内存,Java会将所有内容相同的字符串字面量视为单个String对象,拥有多个指向它的引用。
——Deitel《Java How to Program》
疑问与解答
我理解str1、str2、str6因属于字符串字面量或编译期确定的字面量拼接,指向同一对象,结果为true;str3通过new创建新对象,结果为false。但我不理解最后两个结果:str4与str6、str2与str5的区别是什么?str1是变量而其他是对象吗?我已了解equals()方法及二者的区别,此问题与Stack Overflow相关问题不同,寻求解答。
核心原因解析
- 字符串常量池的作用范围:只有编译期就能确定值的字符串字面量/常量表达式才会被放入字符串常量池。str6的
"Obj"+"ect"是编译期常量拼接,编译器会直接优化成"Object",所以它会指向常量池中的同一个对象。 - substring方法的行为:
substring是运行期执行的方法,它返回的是新创建的String对象(JDK 7及以后版本中,substring会直接生成新的字符数组,不再共享原数组,但核心是会创建新对象),不会放入字符串常量池。所以str4和str5都是运行期生成的新对象,它们和常量池中的str1指向不同的内存地址,彼此之间也不是同一个对象,因此==比较结果为false。 - 变量与对象的区别:str1是引用变量,它指向常量池中的String对象;str4、str5是引用变量,指向的是运行期创建的堆内存中的String对象。本质上所有的String类型变量都是引用,区别在于它们指向的对象是在常量池还是堆中,以及是否是同一个对象实例。
内容的提问来源于stack exchange,提问作者babeyh
相关产品推荐
相关产品推荐

