简体   繁体   English

字符串intern()方法使用混乱

[英]String intern() method usage confusion

We use intern() method for the Strings which are created through new String() so that they will create an entry in String Pool and return the newly created String from the String Pool so that this created string is eligible for use with == operator (as per my understanding). 我们对通过新String()创建的字符串使用intern()方法,以便它们将在字符串池中创建一个条目,并从字符串池返回新创建的字符串,以便此创建的字符串适合与==运算符一起使用(据我了解)。

Then what is the use of creating a new String through constructor? 那么通过构造函数创建新的String有什么用?

When should we use constructor for creating new String? 什么时候应该使用构造函数创建新的String?

new String() can create at-most two Objects of String and at-least one. 新的String()最多可以创建两个String对象,至少一个。 one in constant pool (if same is not present in constant pool) and another in heap memory. 一个在常量池中(如果常量池中不存在),另一个在堆内存中。 constant pool entry is created by interning String object. 常量池条目是通过InterString对象创建的。

intern will create String Literal in Constant pool so that whenever you create String without new keyword it will not create string object. 实习生将在常量池中创建String Literal,以便每当您创建不带new关键字的String时,都不会创建字符串对象。

suppose you have created as 假设您已经创建为

String str= new String("abc");

two object will be created one in constant pool (if "abc" is not present in constant pool). 将在常量池中创建两个对象(如果常量池中不存在“ abc”)。 jvm wil internally call intern for that object. jvm将内部调用该对象的intern。 so next time if you are doing 所以下次如果你在做

String str1= "abc";

no entry will be added to constant pool because only entry can be possible in constant pool for same literal. 不会将任何条目添加到常量池中,因为对于相同的文字,只能在常量池中添加条目。

public native String intern(); java doc says, 

A pool of strings, initially empty, is maintained privately by the class >{@code String}. 最初为空的字符串池由> {@ code String}类私下维护。 When the intern method is invoked, if the pool already >contains a string equal to this {@code String} object as determined by >the {@link #equals(Object)} method, then the string from the pool is >returned. 调用intern方法时,如果池中已经包含一个由{@link #equals(Object)}方法确定的等于此{@code String}对象的字符串,则返回该池中的字符串。 Otherwise, this {@code String} object is added to the pool and >a reference to this {@code String} object is returned. 否则,将此{@code String}对象添加到池中,并返回对此{@code String}对象的引用。 It follows that >for any two strings {@code s} and {@code t}, {@code s.intern() == >t.intern()} is {@code true} if and only if {@code s.equals(t)} is {@code >true}. 因此,对于任意两个字符串{@code s}和{@code t},{@ code s.intern()==> t.intern()}为{@code true},当且仅当{@code s.equals(t)}是{@code> true}。

Let's consider an example: 让我们考虑一个例子:

String temp1 = new String("abcd"); this means, a new object "abcd" will be created in the heap memory and its reference will be linked to temp1 . 这意味着将在heap memory创建一个新对象"abcd"并将其引用链接到temp1

String temp2 = new String("abcd").intern(); this means "abcd" literal will be checked in the String Pool . 这意味着将在String Pool检查"abcd"文字。 If already present, its reference will be linked to newly created temp2 . 如果已经存在,则其引用将链接到新创建的temp2 Else a new entry will be created in String Pool and its reference will be linked to newly created temp2 . 否则,将在String Pool创建一个新条目,并将其引用链接到新创建的temp2

String temp3 = "abcd"; this means "abcd" literal will be checked in the String Pool . 这意味着将在String Pool检查"abcd"文字。 If already present, its reference will be linked to newly created temp2 . 如果已经存在,则其引用将链接到新创建的temp2 Else a new entry will be created in String Pool and its reference will be linked to newly created temp3 . 否则,将在String Pool创建一个新条目,并将其引用链接到新创建的temp3 This conclude that, Java automatically interns String literals . 由此得出结论, Java自动插入String常量

Let's consider another example: 让我们考虑另一个示例:

String s1 = "string-test";

String s2 = new String("string-test");

String s3 = new String("string-test").intern();

if ( s1 == s2 ){
    System.out.println("s1 and s2 are same");
}

if ( s2 == s3 ){
    System.out.println("s2 and s3 are same" );
}

if ( s1 == s3 ){
    System.out.println("s1 and s3 are same" );
}

Output: s1 and s3 are same 输出: s1 and s3 are same

Now when to create a String object using = " " or using new String(" ") ? 现在何时使用= " "或使用new String(" ")创建String对象?

One use case which I came across, 我遇到的一个用例

// imagine a multi-megabyte string here String s = "0123456789012345678901234567890123456789"; String s2 = s.substring(0, 1); s = null;

You'll now have a String s2 which, although it seems to be a one-character string, holds a reference to the gigantic char array created in the String s. 现在,您将拥有一个String s2,尽管它似乎是一个单字符的字符串,但它包含对在String中创建的巨大char数组的引用。 This means the array won't be garbage collected, even though we've explicitly nulled out the String s! 这意味着即使我们显式使String无效,该数组也不会被垃圾回收!

The fix for this is to use String constructor like this: 解决此问题的方法是使用String构造函数,如下所示:

String s2 = new String(s.substring(0, 1));

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM