JDK1.8字符串常量池里存的是String对象还是引用?
Posted flyingrun
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JDK1.8字符串常量池里存的是String对象还是引用?相关的知识,希望对你有一定的参考价值。
??众所周知,JDK1.8版本中,String常量池已经从方法区中的运行时常量池分离到堆中了,那么在堆中的String常量池里存的是String对象还是引用呢?直接查看API:
??翻译:String类的intern()方法:一个初始为空的字符串池,它由类String独自维护。当调用 intern方法时,如果池已经包含一个等于此String对象的字符串(用equals(oject)方法确定),则返回池中的字符串。否则,将此String对象添加到池中,并返回此String对象的引用。 对于任意两个字符串s和t,当且仅当s.equals(t)为true时,s.intern() == t.intern()才为true。所有字面值字符串和字符串赋值常量表达式都使用 intern方法进行操作。
总结
??JDK1.8版本的字符串常量池中存的是字符串对象,以及字符串常量值。
??附上常考面试题:
- 输出结果?创建了几个对象?
String s1 = "abc";
String s2 = "abc";
System.out.println(s1==s2);
??结果输出:
true
??创建了1个对象。采用字面值的方式创建一个字符串时,JVM首先会去字符串池中查找是否存在"abc"这个对象,如果不存在,则在字符串池中创建"abc"这个对象,然后将池中"abc"这个对象的引用地址返回给"abc"对象的引用s1,这样s1会指向池中"abc"这个字符串对象;如果存在,则不创建任何对象,直接将池中"abc"这个对象的地址返回,赋给引用s2。因为s1、s2都是指向同一个字符串池中的"abc"对象,所以结果为true。
- 输出结果?创建了几个对象?
String s3 = new String("xyz");
String s4 = new String("xyz");
System.out.println(s3==s4);
??结果输出:
false
??创建了3个对象。采用new关键字新建一个字符串对象时,JVM首先在字符串池中查找有没有"xyz"这个字符串对象,如果有,则不在池中再去创建"xyz"这个对象了,直接在堆中创建一个"xyz"字符串对象,然后将堆中的这个"xyz"对象的地址返回赋给引用s3,这样,s3就指向了堆中创建的这个"xyz"字符串对象;如果没有,则首先在字符串池中创建一个"xyz"字符串对象,然后再在堆中创建一个"xyz"字符串对象,然后将堆中这个"xyz"字符串对象的地址返回赋给s3引用,这样,s3指向了堆中创建的这个"xyz"字符串对象。s4则指向了堆中创建的另一个"xyz"字符串对象。s3 、s4是两个指向不同对象的引用,结果当然是false。
- 代码详解
String s1 = new StringBuilder().append("ja").append("va1").toString();
System.out.println(s1.intern() == s1);
??输出结果:
true
??详解:会在常量池中复制一个对象,但s1.intern()返回的是堆中的对象的引用,而不是复制在常量池中这个对象的引用,所以既解释了“如果池已经包含一个等于此String对象的字符串(用equals(oject)方法确定),则返回池中的字符串。否则,将此String对象添加到池中,并返回此String对象的引用。”,也解释了s1.intern() == s1。
以上是关于JDK1.8字符串常量池里存的是String对象还是引用?的主要内容,如果未能解决你的问题,请参考以下文章
java中的字符串到底是在方法区的常量池里还是new出来的对象里