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问题及常量池小结的主要内容,如果未能解决你的问题,请参考以下文章

String 类型

String类==与equals常见面试题

==和equals()

java基础知识

java中equal()方法和==的使用

java中equal()方法和==的使用