String类型的==和equals问题及常量池小结
Posted cctvyuzhou
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了String类型的==和equals问题及常量池小结相关的知识,希望对你有一定的参考价值。
public static void main(String[] args) { String str1 = "abc"; String str2 = "abc"; final String str3 = "ab"; String str4 = "ab"; String str5 = str3+"c"; String str6 = str4+"c"; String str7 = "ab"+"c"; String str8 = new String("abc"); System.out.println(str1==str2); System.out.println(str1==str5); System.out.println(str1==str6); System.out.println(str1==str7); System.out.println(str1==str8); }
以上代码的运行结果是什么?
答案是 true、true、false、true、false!!!
从写hello world 开始,大家都知道:
==比较的是栈内存中存放的对象的堆内存地址,用来判断两个对象的地址是否相同,即是否是指向同一个对象。
equals比较的是两个对象的内容是否相同。
按照上述说法,那就是str1和str2、str1和str5以及str1和str7都是指向同一块堆内存。
实际上在用“”创建的字符串都是常量,编译期就已经确定存储到Constant Pool(常量池)中。
即编译期首先常量池分配一个字符串,然后由str1去引用这个字符串;创建str2的时候首先去字符串常量池里找有没有"abc",如果没有,则将"abc"存放进字符串常量池,并令str2指向”abc”,如果已经有”abc” 则直接令str2指向“abc”。所以str1==str2为true。
而str3是用final修饰的变量,当final变量是基本数据类型以及String类型时,如果在编译期间能知道它的确切值,则编译器会把它当做编译期常量使用,所以str3在编译时被当做了常量“ab”使用,str5就和str7一样成为了“ab”+“c”即“abc”就和str2变成了一样,结果也就会和str2一样,所以str1==str5、str1==str7都为true。
str6则是变量str4 append上“c”,是在运行期创建了StringBuilder对象进行了append操作后通过toString()返回了一个字符串对象存在heap上。所以str1==str6为false。
str8是用new()来新建对象的,在编译期无法确定,在运行期执行String str8 = new String(“abc”);时,JVM首先在Constant Pool中查看是否存在字符串对象“abc”,如果不存在该对象,则先在String Pool中创建一个新的字符串对象“abc”,然后执行new String(“abc”)构造方法,在Heap里又创建一个新的字符串对象“abc”(new出来的对象都放在Heap里面),并将引用str8指向Heap中创建的新对象;如果已存在该对象,则不用创建新的字符串对象“abc”,而直接使用Constant Pool中已存在的对象“abc”, 然后执行new String(“abc”)构造方法,在Heap里又创建一个新的字符串对象“abc”,并将引用str8指向Heap中创建的新对象。所以str1==str8为false。
以上是关于String类型的==和equals问题及常量池小结的主要内容,如果未能解决你的问题,请参考以下文章