Java大学教程》在讲到String的intern方法时,提供了一个例子,根据我的对书上以及以及以下资料的解释:
http://blog.csdn.net/ameyume/article/details/5815756#java
http://www.roseindia.net/java/string-examples/string-intern.shtml我认为结果如下:
s1 and s2 are not the same object in memory
s1 and s2 are equal.
s3 and s4 are the same object in memory.
s1 and s3 are the same object in memory.
s2 and s4 are the same object in memory.
s1 and s4 are the same object in memory.
但是运行结果如下:
s1 and s2 are not the same object in memory
s1 and s2 are equal.
s3 and s4 are the same object in memory.
s1 and s3 are not the same object in memory.
s2 and s4 are not the same object in memory.
s1 and s4 are not the same object in memory.
import java.awt.Graphics;
import java.applet.Applet;public class Hello extends Applet
{
String s1, s2, s3, s4;

public void init()
{
s1 = new String( "hello" );
                  s2 = new String( "hello" );
}

public void paint( Graphics g )
{
//Test strings to determine if they are the same object in the memory
if( s1 == s2 )
g.drawString( "s1 and s2 are the same object in memory.", 25, 25 );
else
g.drawString( "s1 and s2 are not the same object in memory.", 25, 25 );
 
//Test strings to determine whether they have the same contents
if( s1.equals( s2 ) )
g.drawString( "s1 and s2 are equal.", 25, 40 );
else
g.drawString( "s1 and s2 are not equal.", 25, 40 );

//Use String intern method to get a unique copy of "hello" refered to by both s3 and s4
s3 = s1.intern();
s4 = s2.intern();

//Test strings to determint if they  are the same object in the memory
if( s3 == s4 )
g.drawString( "s3 and s4 are the same object in memory.", 25, 55 );
else 
g.drawString( "s3 and s4 are not the same object in memory.", 25, 55 );

//Determine if s1 and s3 refer to the same object in the memory
if( s1 == s3 )
g.drawString( "s1 and s3 are the same object in memory.", 25, 70 );
else
g.drawString( "s1 and s3 are not the same object in memory.", 25, 70 );

//Determine if s2 and s4 refer to the same object in the memory
if( s2 == s4 )
g.drawString( "s2 and s4 are the same object in memory.", 25, 85 );
else
g.drawString( "s2 and s4 are not the same object in memory.", 25, 85 );

//Determine if s1 and s4 refer to the same object in the memory
if( s1 == s4 )
g.drawString( "s1 and s4 are the same object in memory.", 25, 100 );
else
g.drawString( "s1 and s4 are not the same object in memory.", 25, 100 );
}
}

解决方案 »

  1.   

    简单点,不精确的,不考虑是在运行期还是类加载时期的,解释一下(因为关于这个String可以啰里八嗦说一大堆):
    先看看Java Language Specification: 3.10.5 String Literals 小节中的一段话:string字面值(比如"abc")总是指向相同的String类实例。这是因为string字面值或者字符串常量表达式都是"interned"。亲,咱再来看看inter的API doc 官方是怎么说的:看这句

    When the intern method is invoked, if the pool already contains a string equal to this String object as determined by the equals(Object) 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.

    当调用intern方法的时候,如果String pool中有一个对象和这个对象用equals判断是一样的话,那么就返回pool中的string对象。否则这个string对象就加到string pool中,并且返回这个对象的引用。OK,看你代码:s1 = new String( "hello" );                
    s2 = new String( "hello" );"hello"这个字符串本身就创建了一个对象内容为hello(我们假设这个对象为X),而且这个对象是被intern了的。
    这段代码等价于:String x = "hello";
    s1 = new String(x);                
    s2 = new String(x);  s1 = new String( "hello" ); 这句代码,因为用的是new,所以他会重新创建一个对象,内容也是hello。然后s1引用这个对象。这个对象和string字面值“hello”创建了的对象(X)不是同一个("hello" 和 new String("hello") 用==,返回的是false);
      s2 = new String( "hello" ); 这句同上句,也创建了一个对象,内容同样为hello,s2引用该对象。他和string字面值“hello”创建了的对象(X)也不是同一个。再看s3,s4:s3 = s1.intern();
    s4 = s2.intern();上面已经解释过intern,s1,s2的内容都是hello,而且string字面值“hello”本身创建了一个对象(X),这个对象已intern并加到了string pool。所以s1.intern();返回的是X,s2.intern();返回的也是X。那么s3,s4就是一样的,不管是用equals还是==。最后s3,s4 引用的对象和String字面值"hello"创建的是同一个,s1引用的是new创建的一个,s2引用的是new创建的另外一个。所以:
    s1 != s2;
    s1 != s3;
    s1 != s4;s2 != s3;
    s2 != s4;s3 == s4;
      

  2.   

    这方法有bug的,我之前已经在iteye发起过讨论了:http://www.iteye.com/topic/1112592
      

  3.   

    1楼的有点问题,在hotspot jdk1.7,JRockit虚拟机上,s1==s3,s2==s4
    hotspot的其他版本的虚拟机都是s1!=s3,s2!=s4
      

  4.   

    不一定的,赌神。要s1,s2是由new创建的对象,而且在创建s1,s2之前已经存在一个由字面值创建的对象,根据语言规范,那么要intern这个由字面值创建的对象,不管hotspot是如何管理这个string pool的,有没有permGen。所以s1.intern != s1; s2.intern != s2;