【问题标题】:String intern() method usage confusionString intern() 方法使用混乱
【发布时间】:2015-02-08 16:31:43
【问题描述】:

我们对通过 new String() 创建的字符串使用 intern() 方法,这样它们将在字符串池中创建一个条目,并从字符串池中返回新创建的字符串,这样创建的字符串就可以用于== 运算符(根据我的理解)。

那么通过构造函数创建一个新的String有什么用呢?

什么时候应该使用构造函数来创建新的字符串?

【问题讨论】:

  • 你在滥用 intern() 方法。永远不要将== 与字符串一起使用,也永远不要使用将字符串作为参数的字符串构造函数。
  • 还有一个(更有用的)字符串构造函数,它需要一个字节数组来创建它——尽管我不确定你是否也需要调用intern()。跨度>
  • @JBNizet 有时测试引用相等性是有正当理由的(例如,使用可区分的字符串引用作为标记值)。但是,是的,不要使用 '==' 来测试两个字符串是否具有相同的

标签: java string


【解决方案1】:

new String() 最多可以创建两个 String 对象,并且至少可以创建一个。一个在常量池中(如果常量池中不存在相同的内容),另一个在堆内存中。 常量池条目是由 intern String 对象创建的。

intern 将在常量池中创建 String Literal,这样每当您创建没有 new 关键字的 String 时,它都不会创建字符串对象。

假设你已经创建为

String str= new String("abc");

两个对象将在常量池中创建一个(如果常量池中不存在“abc”)。 jvm 将在内部为该对象调用实习生。 所以下次如果你在做

String str1= "abc";

不会将任何条目添加到常量池中,因为对于相同的文字,常量池中只能有条目。

【讨论】:

  • 这如何回答“何时使用 String 构造函数”的问题?
  • String 构造函数仅在您的示例中创建 one 字符串。字符串文字 "abc" 不是由 new String("abc") 调用创建的,甚至不是由包含该调用的语句创建的。它是在包含该语句的类文件首次加载到内存时创建的。
  • @jameslarge :您可以查看学习资料。 JVM 主要是为所需的 String 对象调用 intern()。
  • @Tom : 如果你想根据内容比较 String 对象,那么你可以 String 构造函数。并为此投反对票??
  • @Prashant 如果我不想比较字符串?然后呢?而且您应该询问否决者的原因,而不是我。
【解决方案2】:
public native String intern(); java doc says, 

一个字符串池,最初是空的,由类 >{@code String} 私下维护。当调用 intern 方法时,如果池已经 > 包含一个等于此 {@code String} 对象的字符串,该字符串由 > {@link #equals(Object)} 方法确定,则 > 返回池中的字符串。否则,这个 {@code String} 对象被添加到池中并且 > 一个对这个 {@code String} 对象的引用被返回。因此 > 对于任何两个字符串 {@code s} 和 {@code t},{@code s.intern() == >t.intern()} 是 {@code true} 当且仅当 {@code s.equals(t)} 是 {@code >true}。

让我们考虑一个例子:

String temp1 = new String("abcd"); 这意味着,将在heap memory 中创建一个新对象"abcd",其引用将链接到temp1

String temp2 = new String("abcd").intern(); 这意味着"abcd" 文字将在String Pool 中检查。如果已经存在,它的引用将链接到新创建的temp2。否则将在String Pool 中创建一个新条目,其引用将链接到新创建的temp2

String temp3 = "abcd"; 这意味着"abcd" 文字将在String Pool 中检查。如果已经存在,它的引用将链接到新创建的temp2。否则将在String Pool 中创建一个新条目,其引用将链接到新创建的temp3。由此得出结论,Java 自动实习字符串字面量

让我们考虑另一个例子:

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" );
}

输出:s1 and s3 are same

现在何时使用= " "new String(" ") 创建字符串对象?

我遇到的一个用例,

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

您现在将拥有一个 String s2,虽然它看起来是一个单字符的字符串,但它包含对在 String s 中创建的巨大 char 数组的引用。这意味着数组不会被垃圾回收,即使我们已经明确地清空了 String s!

解决方法是像这样使用 String 构造函数:

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

【讨论】:

    猜你喜欢
    • 2014-07-12
    • 2018-10-02
    • 1970-01-01
    • 1970-01-01
    • 2011-03-20
    • 2015-12-12
    • 2013-08-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多