Когда должен мы использовать метод интерна Строки на Строковых литералах

Труба:

Poke(0)
184
задан Ravi 4 January 2018 в 00:48
поделиться

4 ответа

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.

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

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.

226
ответ дан 23 November 2019 в 05:58
поделиться

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

12
ответ дан 23 November 2019 в 05:58
поделиться

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.

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.

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.

20
ответ дан 23 November 2019 в 05:58
поделиться

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

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.

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

EDIT: interned becoming 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.

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.

14
ответ дан 23 November 2019 в 05:58
поделиться
Другие вопросы по тегам:

Похожие вопросы: