2017-05-07 33 views
-1
String Str1= new String("java"); 
String Str3 = new String("java"); 

System.out.println(Str1==Str3); 

第一行代码创建对象str1,其中的内容"java" init都在String池中和堆中。现在Str3会做什么?我知道它在堆中创建Str3关于字符串池中的Str3?第三行做什么?它是否在String池或堆区检查相等性?我知道它给出了错误,但我的问题是,如果Str1和Str3存储在字符串池==应给予真正的权利,因为引用是相同的。如何存储使用new()创建的字符串作为Java中的文字的重复字符串?

+1

您正在创建'Str3'作为** new **对象。由于'=='检查引用,你会得到'false'。 – Maroun

+0

可能重复[如何比较Java中的字符串?](http://stackoverflow.com/questions/513832/how-do-i-compare-strings-in-java) –

+0

我知道它会给出错误。我的问题是如果str1和str2都存储在字符串池==应给予真实。 – ravi

回答

2

第一行代码创建对象str1,其中包含字符串池和堆中的内容“java”init。

其实:

  1. 串池堆的一部分。 (这实际上并不涉及你的错误观念,但它有助于让你的脑海变得直观)。
  2. 对应于“java”文字的字符串对象由类加载器创建,而不是由该语句创建。它是在加载类时创建的 ...不是代码运行时。

所以,其实这句话只有在堆中创建一个字符串对象。

现在Str3会做什么?

第二个语句在堆中创建单个字符串对象...。

根据上面的说明,此语句中使用的“java”字面值的字符串对象是以前创建的。 (事实上​​,如果你查看字节码文件,你会发现文件常量池中只有一个“java”字符串,所以,类加载器甚至不需要创建两个字符串实例和两个字符串实例。一个是创建和interned。)

我知道它在堆中创建Str3 Str3在字符串池中怎么办?

没有。所有字符串文字均在字符串池中创建,并自动将其删除。

第三行做什么?它是否检查字符串池或堆区域中的相等性?

没有。它测试以查看对象引用是否相同;即如果它们是相同的对象。它实际上并不测试它们在哪里。

(你实际上不能直接测试一个String是否在池中,甚至不能测试一个对象是否在堆中。 ..如果JVM为您提供了一种在(常规)堆外分配对象的方法。)

我知道它给出了错误,但我的问题是,如果Str1和Str3存储在字符串池==应给予真正的权利,因为引用是相同的。

它们不在字符串池中。他们是普通的堆对象。

认为它这样,事实==回报false证明,他们不是(两者)在字符串池。因为如果他们都在字符串池中,他们会必须是相同的String对象。 。


这里是JLS上说字符串和身份是什么:

“此外,文字始终是一个字符串是指String类的同一个实例。这是因为字符串文字 - 或者,更通常,使用方法String.intern“常量表达式(§15.28)”的值的字符串将被“interned”,以共享唯一实例。“

这个实习发生在班级加载时。


1 - 规格说明没有说明实习生何时发生。看起来,最近的JVM懒散地解决了一个方法对字符串文字的引用;即,第一次由字节码解释器调用该方法时,实施会发生。但是,这并没有改变上述解释的实质。

+0

它实际上好像是对应于字面值的字符串被创建并且当它第一次被引用时被实施。 (如果在使用文字前多次调用System.identityHashCode(“j”.concat(“ava”).intern())和System#gc,它将打印不同的散列码,在使用文字后它总是打印相同的哈希码)。 – Nevay

+0

@Nevay它与'之前'和'之后'无关。如果您在类的文本或任何其他已加载的类中使用了全部*全部*,*全部*的全部*,则它将在执行前存在于字符串池中。 – EJP

+0

@EJP那么你如何解释这个结果呢? https://ideone.com/204QnH在我看来,它非常清楚地表明,在第一次使用该文字之前,该类的常量池不包含对字符串池中的字符串的引用。 – Nevay

相关问题