美文网首页
关于String的有趣问题

关于String的有趣问题

作者: 兮兮码字的地方 | 来源:发表于2019-09-28 21:58 被阅读0次

    A

    String str1= "abc";
    String str2= new String("abc");
    String str3= str2.intern();
    System.out.print(str1==str2);
    System.out.print(str2==str3);
    System.out.print(str1==str3)

    先说结果,上面三个输出结果是false false true

    根据jvm的内存划分规则:

    在字符串常量中,默认会将对象放入常量池;在字符串变量中,对象是会创建在堆内存中,同时也会在常量池中创建一个字符串对象,赋值到堆内存对象中,并返回堆内存对象引用。

    若在每次赋值的时候使用 String 的 intern 方法,如果常量池中有相同值,就会重复使用该对象,返回对象引用,这样一开始在堆中创建的对象就可以被回收掉。

    所以:

    1.String str1= "abc";这种方式,会在常量池中创建一个值为“abc”的对象,str1引用堆中String对象。

    2.String str2 = new String(“abc”) 这种方式,会创建两个对象,首先在常量池中创建值为“abc”的对象;其次,在调用 new 时,JVM 命令将会调用 String 的构造函数,在堆中创建一个String对象,String 对象中的 char 数组将会引用常量池中字符串"abc” ;最后,str2 引用堆中String对象。

    3.String str3= str2.intern();这种方式,会在常量池中查找是否有同样值为"abc”的对象,发现已经有了,就直接返回常量池中“abc”对象的引用给str3。

    (使用 "abc"常量和使用intern()方法,这两种方式达到的效果其实是一样的。)

    所以str1和str3是同一个引用,都是指向常量池中的对象地址,而str2则是指向的在堆中创建的对象地址的引用。


    再看下面这个例子

    B

    String a =new String("abc").intern();
    String b = new String("abc").intern();
         
    if(a==b) {
        System.out.print("a==b");
    }

    输出结果是true。

    根据jvm规则,

    在一开始字符串"abc"会在加载类时,在常量池中创建一个字符串对象。

    创建 a 变量时,调用 new Sting() 会在堆内存中创建一个 String 对象,String 对象中的 char 数组将会引用常量池中字符串"abc"。在调用 intern 方法之后,会去常量池中查找是否有等于该字符串对象的引用,有就返回引用。

    创建 b 变量时,调用 new Sting() 会在堆内存中创建一个 String 对象,String 对象中的 char 数组将会引用常量池中字符串"abc"。在调用 intern 方法之后,会去常量池中查找是否有等于该字符串对象的引用,有就返回引用。

    而这个过程当中在堆内存中创建的两个对象,由于没有引用指向它,将会被垃圾回收。所以 a 和 b 引用的是同一个对象。

    相关文章

      网友评论

          本文标题:关于String的有趣问题

          本文链接:https://www.haomeiwen.com/subject/zgfxpctx.html