Java教程

通俗易懂的了解String中的intern方法

本文主要是介绍通俗易懂的了解String中的intern方法,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

首先,先看一下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。

 

这篇关于通俗易懂的了解String中的intern方法的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!