首先,先看一下intern方法(JDK1.8)的官方文档:
全是英文,阅读起来有点困难怎么办?没关系,博主对此做了翻译:
返回字符串对象的规范表示形式。
最初为空的字符串池由类字符串私人维护。
调用intern方法时,如果池中已包含一个字符串,该字符串等于由equals(object)方法确定的该字符串对象,则返回池中的字符串。否则,将此字符串对象添加到池中,并返回对该字符串对象的引用。
因此,对于任意两个字符串s和t,s.intern()==t.intern()当且仅当s.equals(t)为真时才为真。
所有文字字符串和字符串值常量表达式都是内部的。字符串文字在Java的第3.10.5节中定义™ 语言规范。
返回值:
与此字符串具有相同内容,但保证来自唯一字符串池的字符串。
还是看不懂怎么办?以下博主将对intern方法进行全面讲解:
要想具体了解String中的intern方法,首先你要了解一下JVM的内存结构,认识串池(StringTable)。
以下是JDK1.6相关的内存结构:
以下是JDK1.8相关的内存结构:
随着内存结构的改变String中的intern方法功能也发生了改变。
本片文章主要以JDK1.8为例,先看以下这段代码:
public class Test{ String s1 = new String(\"a\") + new String(\"b\"); s1.intern();//① String s2 = \"ab\";//② System.out.println(s1 == s2); }
运行结果为true;
具体原因是:当String对象调用intern方法时,如果池中未包含相同的字符串,将此字符串对象添加到池中,并返回对该字符串对象的引用。
运行的主要流程为:
(1)String s1 = new String(“a”) + new String(“b”);
首先创建StringBuilder对象,用于字符串拼接;
然后在堆中创建了String(“a”)对象,然后在字符串常量池中放入字符串\"a\",再做StringBuilder的append操作;
然后在堆中创建了String(“b”)对象,然后在字符串常量池中放入字符串\"b\",再做StringBuilder的append操作;
最后对StringBuilder做toString操作,注意此时只会在堆内存创建对象,并不会在串池中创建。
(2)s1.intern();
常量池中不直接放入\"ab\",而是引用堆中已经创建的String(“ab”)。
(3)String s2 = “ab”;
s2指向字符串常量池中的\"ab\",实际上是指向了堆中的String(“ab”)。
但当我们调换①和②的位置时结果为falus,这是什么原因呢?
调用intern方法时,如果池中已包含一个字符串,该字符串等于由equals(object)方法确定的该字符串对象,则返回池中的字符串。
所以,当调换①和②后,代码将会首先在串池中创建一个“ab”,然后当执行s1.intern()时就会直接返回串池中的\"ab\",但此时堆内存中的String(\"ab\")对象和串池中的\"ab\"不为同一个,于是返回falus。
但别忘了,JDK1.6和JDK1.8却是不同的。
JDK1.6的作用是:检查常量池里是否存在“ab”这么一个字符串,如果存在,就返回池里的字符串,如果不存在,该方法会把“ab”添加到字符串池中(此时这个\"ab\"并不是堆内存中的那个String(”ab“)而是一个新的\"ab\"),然后再返回它的引用。所以如果是JDK1.6下以上两张情况将都返回falus。
来源:https://www.cnblogs.com/wffwh/p/16694591.html
本站部分图文来源于网络,如有侵权请联系删除。