我们什么时候应该在字符串文字上使用实习的字符串方法

时间:2022-09-11 11:40:49

According to String#intern(), intern method is supposed to return the String from the String pool if the String is found in String pool, otherwise a new string object will be added in String pool and the reference of this String is returned.

根据String#intern(),如果在String pool中发现了字符串,那么intern方法应该从String pool返回字符串,否则将在String pool中添加一个新的String对象,并返回该字符串的引用。

So i tried this:

所以我试着:

String s1 = "Rakesh";
String s2 = "Rakesh";
String s3 = "Rakesh".intern();

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

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

I was expecting that s1 and s3 are same will be printed as s3 is interned, and s1 and s2 are same will not be printed. But the result is: both lines are printed. So that means, by default String constants are interned. But if it is so, then why do we need the intern method? In other words when should we use this method?

我原以为s1和s3是一样的,因为s3是一样的,s1和s2是一样的,不会打印。但结果是:两行都打印出来了。这意味着,默认情况下字符串常数会被代入。但如果是这样,那我们为什么需要实习方法呢?换句话说,我们什么时候应该使用这个方法?

14 个解决方案

#1


208  

Java automatically interns String literals. This means that in many cases, the == operator appears to work for Strings in the same way that it does for ints or other primitive values.

Java自动实习生字符串文字。这意味着在许多情况下,==运算符对字符串的处理方式与ints或其他原始值的处理方式相同。

Since interning is automatic for String literals, the intern() method is to be used on Strings constructed with new String()

由于对字符串文字来说,interning是自动执行的,因此实习生()方法将用于使用新字符串()构造的字符串

Using your example:

用你的例子:

String s1 = "Rakesh";
String s2 = "Rakesh";
String s3 = "Rakesh".intern();
String s4 = new String("Rakesh");
String s5 = new String("Rakesh").intern();

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

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

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

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

will return:

将返回:

s1 and s2 are same
s1 and s3 are same
s1 and s5 are same

Refer to JavaTechniques "String Equality and Interning" for more information.

有关更多信息,请参阅JavaTechniques的“字符串相等和交错”。

#2


16  

On a recent project, some huge data structures were set up with data that was read in from a database (and hence not String constants/literals) but with a huge amount of duplication. It was a banking application, and things like the names of a modest set (maybe 100 or 200) corporations appeared all over the place. The data structures were already large, and if all those corp names had been unique objects they would have overflowed memory. Instead, all the data structures had references to the same 100 or 200 String objects, thus saving lots of space.

在最近的一个项目中,一些巨大的数据结构是用从数据库中读取的数据(因此不是字符串常量/文本)建立的,而是大量的重复。这是一个银行应用程序,像一个普通的公司(可能是100或200家)的名字出现在各处。数据结构已经很大了,如果所有这些corp名称都是唯一的对象,它们就会溢出内存。相反,所有的数据结构都引用了相同的100或200个字符串对象,从而节省了大量空间。

Another small advantage of interned Strings is that == can be used (successfully!) to compare Strings if all involved strings are guaranteed to be interned. Apart from the leaner syntax, this is also a performance enhancement. But as others have pointed out, doing this harbors a great risk of introducing programming errors, so this should be done only as a desparate measure of last resort.

interned字符串的另一个小优势是,如果保证所有涉及的字符串都被interned,则可以使用==(成功!)来比较字符串。除了更简洁的语法之外,这也是一种性能增强。但正如其他人所指出的那样,这样做会带来引入编程错误的巨大风险,因此,这只能作为一种最后手段。

The downside is that interning a String takes more time than simply throwing it on the heap, and that the space for interned Strings may be limited, depending on the Java implementation. It's best done when you're dealing with a known reasonable number of Strings with many duplications.

缺点是,插入一个字符串比简单地将它扔到堆上要花费更多的时间,而且根据Java的实现,插入字符串的空间可能是有限的。当你处理一个已知的合理数量的字符串并且有很多重复的时候,这是最好的。

#3


13  

I want to add my 2 cents on using == with interned strings.

我想在使用==和交错字符串时增加2分。

The first thing String.equals does is this==object.

字符串的第一件事。= = =对象。

So although there is some miniscule performance gain ( you are not calling a method), from the maintainer point of view using == is a nightmare, because some interned strings have a tendency to become non-interned.

因此,尽管有一些微小的性能增益(您不是在调用方法),但是从维护人员的角度使用==是一场噩梦,因为一些插入的字符串有可能变为非interned。

So I suggest not to rely on special case of == for interned strings, but always use equals as Gosling intended.

因此,我建议不要依赖于特殊情况下的==,但要始终使用=作为Gosling的意图。

EDIT: interned becoming non-interned:

编辑:实习成为non-interned:

V1.0
public class MyClass
{
  private String reference_val;

  ...

  private boolean hasReferenceVal ( final String[] strings )
  {
    for ( String s : strings )
    {
      if ( s == reference_val )
      {
        return true;
      }
    }

    return false;
  }

  private void makeCall ( )
  {
     final String[] interned_strings =  { ... init with interned values ... };

     if ( hasReference( interned_strings ) )
     {
        ...
     }
  }
}

In version 2.0 maintainer decided to make hasReferenceVal public, without going into much detail that it expects an array of interned strings.

在2.0版本中,维修工决定将hasReferenceVal公开,而不需要详细说明它所期望的一组内嵌字符串。

V2.0
public class MyClass
{
  private String reference_val;

  ...

  public boolean hasReferenceVal ( final String[] strings )
  {
    for ( String s : strings )
    {
      if ( s == reference_val )
      {
        return true;
      }
    }

    return false;
  }

  private void makeCall ( )
  {
     final String[] interned_strings =  { ... init with interned values ... };

     if ( hasReference( interned_strings ) )
     {
        ...
     }
  }
}

Now you have a bug, that may be very hard to find, because in majority of cases array contains literal values, and sometimes a non-literal string is used. If equals were used instead of == then hasReferenceVal would have still continue to work. Once again, performance gain is miniscule, but maintenance cost is high.

现在您有了一个bug,这个bug可能很难找到,因为在大多数情况下,数组包含文字值,有时使用非文字字符串。如果使用=而不是==,那么hasReferenceVal仍然可以工作。再说一次,性能的提高是微乎其微的,但是维护成本却很高。

#4


10  

String literals and constants are interned by default. That is, "foo" == "foo" (declared by the String literals), but new String("foo") != new String("foo").

默认情况下字符串常量和常量将被保存。也就是说,“foo”=“foo”(由字符串文字声明),但是新字符串(“foo”)!=新字符串(“foo”)。

#5


3  

you should make out two period time which are compile time and runtime time.for example:

您应该在编译时和运行时两段时间内完成。例如:

//example 1 
"test" == "test" // --> true 
"test" == "te" + "st" // --> true

//example 2 
"test" == "!test".substring(1) // --> false
"test" == "!test".substring(1).intern() // --> true

in the one hand,in the example 1,we find the results are all return true,because in the compile time,the jvm will put the "test" to the pool of literal strings,if the jvm find "test" exists,then it will use the exists one,in example 1,the "test" strings are all point to the same memory address,so the example 1 will return true. in the other hand,in the example 2,the method of substring() execute in the runtime time, in the case of "test" == "!test".substring(1),the pool will create two string object,"test" and "!test",so they are different reference objects,so this case will return false,in the case of "test" == "!test".substring(1).intern(),the method of intern() will put the ""!test".substring(1)" to the pool of literal strings,so in this case,they are same reference objects,so will return true.

在一方面,在1的例子中,我们发现结果都返回true,因为在编译时,jvm将“测试”的字符串,如果jvm找到“测试”存在,那么它将使用一个存在,在例1中,“测试”字符串都是指向同一个内存地址,所以示例1将返回true。另一方面,在示例2中,substring()方法在运行时执行,在“test”==“!test”.substring(1)中,池将创建两个字符串对象“test”和“!”测试”,所以它们是不同的引用对象,所以本例将返回false,在“test”=“!test”.substring(1).intern()的方法会将“”!test”.substring(1)”放到字符串的池中,所以在本例中,它们是相同的引用对象,所以返回true。

#6


2  

http://en.wikipedia.org/wiki/String_interning

http://en.wikipedia.org/wiki/String_interning

string interning is a method of storing only one copy of each distinct string value, which must be immutable. Interning strings makes some string processing tasks more time- or space-efficient at the cost of requiring more time when the string is created or interned. The distinct values are stored in a string intern pool.

string interning是一种只存储每个不同字符串值的一个副本的方法,它必须是不可变的。交错字符串使一些字符串处理任务的时间或空间效率更高,但在创建或插入字符串时需要更多时间。不同的值存储在字符串实习生池中。

#7


1  

Interned Strings avoid duplicate Strings. Interning saves RAM at the expense of more CPU time to detect and replace duplicate Strings. There is only one copy of each String that has been interned, no matter how many references point to it. Since Strings are immutable, if two different methods incidentally use the same String, they can share a copy of the same String. The process of converting duplicated Strings to shared ones is called interning.String.intern() gives you the address of the canonical master String. You can compare interned Strings with simple == (which compares pointers) instead of equals which compares the characters of the String one by one. Because Strings are immutable, the intern process is free to further save space, for example, by not creating a separate String literal for "pot" when it exists as a substring of some other literal such as "hippopotamus".

内嵌的字符串避免重复的字符串。Interning节省RAM的开销是牺牲更多的CPU时间来检测和替换重复的字符串。每个字符串只有一个副本,不管有多少引用指向它。由于字符串是不可变的,如果两个不同的方法偶然使用相同的字符串,它们可以共享相同字符串的副本。将复制的字符串转换为共享字符串的过程称为intern. String.intern()给出了规范主字符串的地址。您可以将交错的字符串与simple ==(比较指针)进行比较,而不是将字符串的字符逐一进行比较。因为字符串是不可变的,所以实习过程可以*地进一步节省空间,例如,当“pot”作为其他文字的子字符串(如“hippopotamus”)存在时,它不会为“pot”创建单独的字符串文字。

To see more http://mindprod.com/jgloss/interned.html

看到更多的http://mindprod.com/jgloss/interned.html

#8


1  

String s1 = "Anish";
        String s2 = "Anish";

        String s3 = new String("Anish");

        /*
         * When the intern method is invoked, if the pool already contains a
         * string equal to this String object as determined by the
         * method, then the string from the pool is
         * returned. Otherwise, this String object is added to the
         * pool and a reference to this String object is returned.
         */
        String s4 = new String("Anish").intern();
        if (s1 == s2) {
            System.out.println("s1 and s2 are same");
        }

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

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

OUTPUT

输出

s1 and s2 are same
s1 and s4 are same

#9


1  

String p1 = "example";
String p2 = "example";
String p3 = "example".intern();
String p4 = p2.intern();
String p5 = new String(p3);
String p6 = new String("example");
String p7 = p6.intern();

if (p1 == p2)
    System.out.println("p1 and p2 are the same");
if (p1 == p3)
    System.out.println("p1 and p3 are the same");
if (p1 == p4)
    System.out.println("p1 and p4 are the same");
if (p1 == p5)
    System.out.println("p1 and p5 are the same");
if (p1 == p6)
    System.out.println("p1 and p6 are the same");
if (p1 == p6.intern())
    System.out.println("p1 and p6 are the same when intern is used");
if (p1 == p7)
    System.out.println("p1 and p7 are the same");

When two strings are created independently, intern() allows you to compare them and also it helps you in creating a reference in the string pool if the reference didn't exist before.

当两个字符串独立创建时,intern()允许您对它们进行比较,而且如果引用以前不存在,它还可以帮助您在字符串池中创建引用。

When you use String s = new String(hi), java creates a new instance of the string, but when you use String s = "hi", java checks if there is an instance of word "hi" in the code or not and if it exists, it just returns the reference.

当您使用String s = new String(hi)时,java会创建一个新的字符串实例,但是当您使用String s = "hi"时,java会检查代码中是否有单词“hi”的实例,如果有的话,它只返回引用。

Since comparing strings is based on reference, intern() helps in you creating a reference and allows you to compare the contents of the strings.

因为比较字符串是基于引用的,所以intern()可以帮助您创建引用并允许您比较字符串的内容。

When you use intern() in the code, it clears of the space used by the string referring to the same object and just returns the reference of the already existing same object in memory.

当您在代码中使用intern()时,它会清除引用相同对象的字符串所使用的空间,并只返回内存中已存在的相同对象的引用。

But in case of p5 when you are using:

但如果是p5,当你使用

String p5 = new String(p3);

Only contents of p3 are copied and p5 is created newly. So it is not interned.

只有p3的内容被复制,p5是新创建的。所以它没有被拘留。

So the output will be:

所以输出是:

p1 and p2 are the same
p1 and p3 are the same
p1 and p4 are the same
p1 and p6 are the same when intern is used
p1 and p7 are the same

#10


1  

Learn Java String Intern - once for all

Strings in java are immutable objects by design. Therefore, two string objects even with same value will be different objects by default. However, if we wish to save memory, we could indicate to use same memory by a concept called string intern.

java中的字符串是不可变的对象。因此,两个具有相同值的字符串对象在默认情况下将是不同的对象。但是,如果我们希望保存内存,我们可以使用一个名为string intern的概念来指示使用相同的内存。

The below rules would help you understand the concept in clear terms:

下面的规则可以帮助你清楚地理解这个概念:

  1. String class maintains an intern-pool which is initially empty. This pool must guarantee to contain string objects with only unique values.
  2. String类维护一个初始为空的内部池。这个池必须保证包含只有唯一值的字符串对象。
  3. All string literals having same value must be considered same memory-location object because they have otherwise no notion of distinction. Therefore, all such literals with same value will make a single entry in the intern-pool and will refer to same memory location.
  4. 所有具有相同值的字符串文字都必须被视为相同的内存-位置对象,因为它们没有区分的概念。因此,所有这些具有相同值的文字将在internet池中创建一个条目,并将引用相同的内存位置。
  5. Concatenation of two or more literals is also a literal. (Therefore rule #2 will be applicable for them)
  6. 两个或多个字面值的连接也是一个字面值。(因此第2条适用于他们)
  7. Each string created as object (i.e. by any other method except as literal) will have different memory locations and will not make any entry in the intern-pool
  8. 作为对象创建的每个字符串(例如,除文字外的任何其他方法)将具有不同的内存位置,并且不会在internet池中创建任何条目
  9. Concatenation of literals with non-literals will make a non-literal. Thus, the resultant object will have a new memory location and will NOT make an entry in the intern-pool.
  10. 将文字与非文字连接在一起将构成非文字。因此,生成的对象将有一个新的内存位置,并且不会在internet池中创建一个条目。
  11. Invoking intern method on a string object, either creates a new object that enters the intern-pool or return an existing object from the pool that has same value. The invocation on any object which is not in the intern-pool, does NOT move the object to the pool. It rather creates another object that enters the pool.
  12. 在字符串对象上调用intern方法,要么创建一个进入internet池的新对象,要么从具有相同值的池中返回一个现有对象。对任何不在internet池中的对象的调用不会将对象移动到池中。而是创建另一个进入池的对象。

Example:

例子:

String s1=new String (“abc”);
String s2=new String (“abc”);
If (s1==s2)  //would return false  by rule #4
If (“abc” == “a”+”bc” )  //would return true by rules #2 and #3
If (“abc” == s1 )  //would return false  by rules #1,2 and #4
If (“abc” == s1.intern() )  //would return true  by rules #1,2,4 and #6
If ( s1 == s2.intern() )      //wound return false by rules #1,4, and #6

Note: The motivational cases for string intern are not discussed here. However, saving of memory will definitely be one of the primary objectives.

注:这里不讨论字符串实习的动机案例。然而,节省内存肯定是主要目标之一。

#11


1  

    public static void main(String[] args) {
    // TODO Auto-generated method stub
    String s1 = "test";
    String s2 = new String("test");
    System.out.println(s1==s2);              //false
    System.out.println(s1==s2.intern());    //true --> because this time compiler is checking from string constant pool.
}

#12


0  

Why can't string literals be used in the places where intern is requried to use? String literal usage by default will reuse the existing string literals. So why do we need to create new String("something).intern() instead of just assigning "something" ?

为什么在要求实习生使用的地方不能使用字符串?默认情况下,字符串文字使用将重用现有的字符串文字。那么,为什么我们需要创建新的String(“something”).intern()而不是仅仅分配“something”呢?

#13


0  

string intern() method is used to create an exact copy of heap string object in string constant pool. The string objects in the string constant pool are automatically interned but string objects in heap are not. The main use of creating interns is to save the memory space and to perform faster comparison of string objects.

string intern()方法用于在string常量池中创建heap string对象的精确副本。字符串常量池中的字符串对象将被自动插入,而堆中的字符串对象则不是。创建实习生的主要用途是保存内存空间并执行更快的字符串对象比较。

Source : What is string intern in java?

源:java中的string intern是什么?

#14


0  

As you said, that string intern() method will first find from the String pool, if it finds, then it will return the object that points to that, or will add a new String into the pool.

正如您所说,string intern()方法将首先从字符串池中找到,如果找到,那么它将返回指向该对象的对象,或者将向池中添加一个新的字符串。

    String s1 = "Hello";
    String s2 = "Hello";
    String s3 = "Hello".intern();
    String s4 = new String("Hello");

    System.out.println(s1 == s2);//true
    System.out.println(s1 == s3);//true
    System.out.println(s1 == s4.intern());//true

The s1 and s2 are two objects pointing to the String pool "Hello", and using "Hello".intern() will find that s1 and s2. So "s1 == s3" returns true, as well as to the s3.intern().

s1和s2是指向字符串池“Hello”的两个对象,使用“Hello”.intern()将发现s1和s2。因此,“s1 = s3”返回true, s3.intern()也是如此。

#1


208  

Java automatically interns String literals. This means that in many cases, the == operator appears to work for Strings in the same way that it does for ints or other primitive values.

Java自动实习生字符串文字。这意味着在许多情况下,==运算符对字符串的处理方式与ints或其他原始值的处理方式相同。

Since interning is automatic for String literals, the intern() method is to be used on Strings constructed with new String()

由于对字符串文字来说,interning是自动执行的,因此实习生()方法将用于使用新字符串()构造的字符串

Using your example:

用你的例子:

String s1 = "Rakesh";
String s2 = "Rakesh";
String s3 = "Rakesh".intern();
String s4 = new String("Rakesh");
String s5 = new String("Rakesh").intern();

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

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

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

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

will return:

将返回:

s1 and s2 are same
s1 and s3 are same
s1 and s5 are same

Refer to JavaTechniques "String Equality and Interning" for more information.

有关更多信息,请参阅JavaTechniques的“字符串相等和交错”。

#2


16  

On a recent project, some huge data structures were set up with data that was read in from a database (and hence not String constants/literals) but with a huge amount of duplication. It was a banking application, and things like the names of a modest set (maybe 100 or 200) corporations appeared all over the place. The data structures were already large, and if all those corp names had been unique objects they would have overflowed memory. Instead, all the data structures had references to the same 100 or 200 String objects, thus saving lots of space.

在最近的一个项目中,一些巨大的数据结构是用从数据库中读取的数据(因此不是字符串常量/文本)建立的,而是大量的重复。这是一个银行应用程序,像一个普通的公司(可能是100或200家)的名字出现在各处。数据结构已经很大了,如果所有这些corp名称都是唯一的对象,它们就会溢出内存。相反,所有的数据结构都引用了相同的100或200个字符串对象,从而节省了大量空间。

Another small advantage of interned Strings is that == can be used (successfully!) to compare Strings if all involved strings are guaranteed to be interned. Apart from the leaner syntax, this is also a performance enhancement. But as others have pointed out, doing this harbors a great risk of introducing programming errors, so this should be done only as a desparate measure of last resort.

interned字符串的另一个小优势是,如果保证所有涉及的字符串都被interned,则可以使用==(成功!)来比较字符串。除了更简洁的语法之外,这也是一种性能增强。但正如其他人所指出的那样,这样做会带来引入编程错误的巨大风险,因此,这只能作为一种最后手段。

The downside is that interning a String takes more time than simply throwing it on the heap, and that the space for interned Strings may be limited, depending on the Java implementation. It's best done when you're dealing with a known reasonable number of Strings with many duplications.

缺点是,插入一个字符串比简单地将它扔到堆上要花费更多的时间,而且根据Java的实现,插入字符串的空间可能是有限的。当你处理一个已知的合理数量的字符串并且有很多重复的时候,这是最好的。

#3


13  

I want to add my 2 cents on using == with interned strings.

我想在使用==和交错字符串时增加2分。

The first thing String.equals does is this==object.

字符串的第一件事。= = =对象。

So although there is some miniscule performance gain ( you are not calling a method), from the maintainer point of view using == is a nightmare, because some interned strings have a tendency to become non-interned.

因此,尽管有一些微小的性能增益(您不是在调用方法),但是从维护人员的角度使用==是一场噩梦,因为一些插入的字符串有可能变为非interned。

So I suggest not to rely on special case of == for interned strings, but always use equals as Gosling intended.

因此,我建议不要依赖于特殊情况下的==,但要始终使用=作为Gosling的意图。

EDIT: interned becoming non-interned:

编辑:实习成为non-interned:

V1.0
public class MyClass
{
  private String reference_val;

  ...

  private boolean hasReferenceVal ( final String[] strings )
  {
    for ( String s : strings )
    {
      if ( s == reference_val )
      {
        return true;
      }
    }

    return false;
  }

  private void makeCall ( )
  {
     final String[] interned_strings =  { ... init with interned values ... };

     if ( hasReference( interned_strings ) )
     {
        ...
     }
  }
}

In version 2.0 maintainer decided to make hasReferenceVal public, without going into much detail that it expects an array of interned strings.

在2.0版本中,维修工决定将hasReferenceVal公开,而不需要详细说明它所期望的一组内嵌字符串。

V2.0
public class MyClass
{
  private String reference_val;

  ...

  public boolean hasReferenceVal ( final String[] strings )
  {
    for ( String s : strings )
    {
      if ( s == reference_val )
      {
        return true;
      }
    }

    return false;
  }

  private void makeCall ( )
  {
     final String[] interned_strings =  { ... init with interned values ... };

     if ( hasReference( interned_strings ) )
     {
        ...
     }
  }
}

Now you have a bug, that may be very hard to find, because in majority of cases array contains literal values, and sometimes a non-literal string is used. If equals were used instead of == then hasReferenceVal would have still continue to work. Once again, performance gain is miniscule, but maintenance cost is high.

现在您有了一个bug,这个bug可能很难找到,因为在大多数情况下,数组包含文字值,有时使用非文字字符串。如果使用=而不是==,那么hasReferenceVal仍然可以工作。再说一次,性能的提高是微乎其微的,但是维护成本却很高。

#4


10  

String literals and constants are interned by default. That is, "foo" == "foo" (declared by the String literals), but new String("foo") != new String("foo").

默认情况下字符串常量和常量将被保存。也就是说,“foo”=“foo”(由字符串文字声明),但是新字符串(“foo”)!=新字符串(“foo”)。

#5


3  

you should make out two period time which are compile time and runtime time.for example:

您应该在编译时和运行时两段时间内完成。例如:

//example 1 
"test" == "test" // --> true 
"test" == "te" + "st" // --> true

//example 2 
"test" == "!test".substring(1) // --> false
"test" == "!test".substring(1).intern() // --> true

in the one hand,in the example 1,we find the results are all return true,because in the compile time,the jvm will put the "test" to the pool of literal strings,if the jvm find "test" exists,then it will use the exists one,in example 1,the "test" strings are all point to the same memory address,so the example 1 will return true. in the other hand,in the example 2,the method of substring() execute in the runtime time, in the case of "test" == "!test".substring(1),the pool will create two string object,"test" and "!test",so they are different reference objects,so this case will return false,in the case of "test" == "!test".substring(1).intern(),the method of intern() will put the ""!test".substring(1)" to the pool of literal strings,so in this case,they are same reference objects,so will return true.

在一方面,在1的例子中,我们发现结果都返回true,因为在编译时,jvm将“测试”的字符串,如果jvm找到“测试”存在,那么它将使用一个存在,在例1中,“测试”字符串都是指向同一个内存地址,所以示例1将返回true。另一方面,在示例2中,substring()方法在运行时执行,在“test”==“!test”.substring(1)中,池将创建两个字符串对象“test”和“!”测试”,所以它们是不同的引用对象,所以本例将返回false,在“test”=“!test”.substring(1).intern()的方法会将“”!test”.substring(1)”放到字符串的池中,所以在本例中,它们是相同的引用对象,所以返回true。

#6


2  

http://en.wikipedia.org/wiki/String_interning

http://en.wikipedia.org/wiki/String_interning

string interning is a method of storing only one copy of each distinct string value, which must be immutable. Interning strings makes some string processing tasks more time- or space-efficient at the cost of requiring more time when the string is created or interned. The distinct values are stored in a string intern pool.

string interning是一种只存储每个不同字符串值的一个副本的方法,它必须是不可变的。交错字符串使一些字符串处理任务的时间或空间效率更高,但在创建或插入字符串时需要更多时间。不同的值存储在字符串实习生池中。

#7


1  

Interned Strings avoid duplicate Strings. Interning saves RAM at the expense of more CPU time to detect and replace duplicate Strings. There is only one copy of each String that has been interned, no matter how many references point to it. Since Strings are immutable, if two different methods incidentally use the same String, they can share a copy of the same String. The process of converting duplicated Strings to shared ones is called interning.String.intern() gives you the address of the canonical master String. You can compare interned Strings with simple == (which compares pointers) instead of equals which compares the characters of the String one by one. Because Strings are immutable, the intern process is free to further save space, for example, by not creating a separate String literal for "pot" when it exists as a substring of some other literal such as "hippopotamus".

内嵌的字符串避免重复的字符串。Interning节省RAM的开销是牺牲更多的CPU时间来检测和替换重复的字符串。每个字符串只有一个副本,不管有多少引用指向它。由于字符串是不可变的,如果两个不同的方法偶然使用相同的字符串,它们可以共享相同字符串的副本。将复制的字符串转换为共享字符串的过程称为intern. String.intern()给出了规范主字符串的地址。您可以将交错的字符串与simple ==(比较指针)进行比较,而不是将字符串的字符逐一进行比较。因为字符串是不可变的,所以实习过程可以*地进一步节省空间,例如,当“pot”作为其他文字的子字符串(如“hippopotamus”)存在时,它不会为“pot”创建单独的字符串文字。

To see more http://mindprod.com/jgloss/interned.html

看到更多的http://mindprod.com/jgloss/interned.html

#8


1  

String s1 = "Anish";
        String s2 = "Anish";

        String s3 = new String("Anish");

        /*
         * When the intern method is invoked, if the pool already contains a
         * string equal to this String object as determined by the
         * method, then the string from the pool is
         * returned. Otherwise, this String object is added to the
         * pool and a reference to this String object is returned.
         */
        String s4 = new String("Anish").intern();
        if (s1 == s2) {
            System.out.println("s1 and s2 are same");
        }

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

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

OUTPUT

输出

s1 and s2 are same
s1 and s4 are same

#9


1  

String p1 = "example";
String p2 = "example";
String p3 = "example".intern();
String p4 = p2.intern();
String p5 = new String(p3);
String p6 = new String("example");
String p7 = p6.intern();

if (p1 == p2)
    System.out.println("p1 and p2 are the same");
if (p1 == p3)
    System.out.println("p1 and p3 are the same");
if (p1 == p4)
    System.out.println("p1 and p4 are the same");
if (p1 == p5)
    System.out.println("p1 and p5 are the same");
if (p1 == p6)
    System.out.println("p1 and p6 are the same");
if (p1 == p6.intern())
    System.out.println("p1 and p6 are the same when intern is used");
if (p1 == p7)
    System.out.println("p1 and p7 are the same");

When two strings are created independently, intern() allows you to compare them and also it helps you in creating a reference in the string pool if the reference didn't exist before.

当两个字符串独立创建时,intern()允许您对它们进行比较,而且如果引用以前不存在,它还可以帮助您在字符串池中创建引用。

When you use String s = new String(hi), java creates a new instance of the string, but when you use String s = "hi", java checks if there is an instance of word "hi" in the code or not and if it exists, it just returns the reference.

当您使用String s = new String(hi)时,java会创建一个新的字符串实例,但是当您使用String s = "hi"时,java会检查代码中是否有单词“hi”的实例,如果有的话,它只返回引用。

Since comparing strings is based on reference, intern() helps in you creating a reference and allows you to compare the contents of the strings.

因为比较字符串是基于引用的,所以intern()可以帮助您创建引用并允许您比较字符串的内容。

When you use intern() in the code, it clears of the space used by the string referring to the same object and just returns the reference of the already existing same object in memory.

当您在代码中使用intern()时,它会清除引用相同对象的字符串所使用的空间,并只返回内存中已存在的相同对象的引用。

But in case of p5 when you are using:

但如果是p5,当你使用

String p5 = new String(p3);

Only contents of p3 are copied and p5 is created newly. So it is not interned.

只有p3的内容被复制,p5是新创建的。所以它没有被拘留。

So the output will be:

所以输出是:

p1 and p2 are the same
p1 and p3 are the same
p1 and p4 are the same
p1 and p6 are the same when intern is used
p1 and p7 are the same

#10


1  

Learn Java String Intern - once for all

Strings in java are immutable objects by design. Therefore, two string objects even with same value will be different objects by default. However, if we wish to save memory, we could indicate to use same memory by a concept called string intern.

java中的字符串是不可变的对象。因此,两个具有相同值的字符串对象在默认情况下将是不同的对象。但是,如果我们希望保存内存,我们可以使用一个名为string intern的概念来指示使用相同的内存。

The below rules would help you understand the concept in clear terms:

下面的规则可以帮助你清楚地理解这个概念:

  1. String class maintains an intern-pool which is initially empty. This pool must guarantee to contain string objects with only unique values.
  2. String类维护一个初始为空的内部池。这个池必须保证包含只有唯一值的字符串对象。
  3. All string literals having same value must be considered same memory-location object because they have otherwise no notion of distinction. Therefore, all such literals with same value will make a single entry in the intern-pool and will refer to same memory location.
  4. 所有具有相同值的字符串文字都必须被视为相同的内存-位置对象,因为它们没有区分的概念。因此,所有这些具有相同值的文字将在internet池中创建一个条目,并将引用相同的内存位置。
  5. Concatenation of two or more literals is also a literal. (Therefore rule #2 will be applicable for them)
  6. 两个或多个字面值的连接也是一个字面值。(因此第2条适用于他们)
  7. Each string created as object (i.e. by any other method except as literal) will have different memory locations and will not make any entry in the intern-pool
  8. 作为对象创建的每个字符串(例如,除文字外的任何其他方法)将具有不同的内存位置,并且不会在internet池中创建任何条目
  9. Concatenation of literals with non-literals will make a non-literal. Thus, the resultant object will have a new memory location and will NOT make an entry in the intern-pool.
  10. 将文字与非文字连接在一起将构成非文字。因此,生成的对象将有一个新的内存位置,并且不会在internet池中创建一个条目。
  11. Invoking intern method on a string object, either creates a new object that enters the intern-pool or return an existing object from the pool that has same value. The invocation on any object which is not in the intern-pool, does NOT move the object to the pool. It rather creates another object that enters the pool.
  12. 在字符串对象上调用intern方法,要么创建一个进入internet池的新对象,要么从具有相同值的池中返回一个现有对象。对任何不在internet池中的对象的调用不会将对象移动到池中。而是创建另一个进入池的对象。

Example:

例子:

String s1=new String (“abc”);
String s2=new String (“abc”);
If (s1==s2)  //would return false  by rule #4
If (“abc” == “a”+”bc” )  //would return true by rules #2 and #3
If (“abc” == s1 )  //would return false  by rules #1,2 and #4
If (“abc” == s1.intern() )  //would return true  by rules #1,2,4 and #6
If ( s1 == s2.intern() )      //wound return false by rules #1,4, and #6

Note: The motivational cases for string intern are not discussed here. However, saving of memory will definitely be one of the primary objectives.

注:这里不讨论字符串实习的动机案例。然而,节省内存肯定是主要目标之一。

#11


1  

    public static void main(String[] args) {
    // TODO Auto-generated method stub
    String s1 = "test";
    String s2 = new String("test");
    System.out.println(s1==s2);              //false
    System.out.println(s1==s2.intern());    //true --> because this time compiler is checking from string constant pool.
}

#12


0  

Why can't string literals be used in the places where intern is requried to use? String literal usage by default will reuse the existing string literals. So why do we need to create new String("something).intern() instead of just assigning "something" ?

为什么在要求实习生使用的地方不能使用字符串?默认情况下,字符串文字使用将重用现有的字符串文字。那么,为什么我们需要创建新的String(“something”).intern()而不是仅仅分配“something”呢?

#13


0  

string intern() method is used to create an exact copy of heap string object in string constant pool. The string objects in the string constant pool are automatically interned but string objects in heap are not. The main use of creating interns is to save the memory space and to perform faster comparison of string objects.

string intern()方法用于在string常量池中创建heap string对象的精确副本。字符串常量池中的字符串对象将被自动插入,而堆中的字符串对象则不是。创建实习生的主要用途是保存内存空间并执行更快的字符串对象比较。

Source : What is string intern in java?

源:java中的string intern是什么?

#14


0  

As you said, that string intern() method will first find from the String pool, if it finds, then it will return the object that points to that, or will add a new String into the pool.

正如您所说,string intern()方法将首先从字符串池中找到,如果找到,那么它将返回指向该对象的对象,或者将向池中添加一个新的字符串。

    String s1 = "Hello";
    String s2 = "Hello";
    String s3 = "Hello".intern();
    String s4 = new String("Hello");

    System.out.println(s1 == s2);//true
    System.out.println(s1 == s3);//true
    System.out.println(s1 == s4.intern());//true

The s1 and s2 are two objects pointing to the String pool "Hello", and using "Hello".intern() will find that s1 and s2. So "s1 == s3" returns true, as well as to the s3.intern().

s1和s2是指向字符串池“Hello”的两个对象,使用“Hello”.intern()将发现s1和s2。因此,“s1 = s3”返回true, s3.intern()也是如此。