【问题标题】:Count Distinct String Object Instances计算不同的字符串对象实例
【发布时间】:2016-01-19 17:26:44
【问题描述】:

在以下代码段中创建了多少不同的String 对象实例?

String s1 = new String("hello");
String s2 = "GoodBye";
String s3 = s1;

不确定我在这里的所有推理。

通过使用从String 类创建实例的关键字new,我猜它必须是一个对象。但是,我很困惑,new 之后的 String 现在是否被视为一种方法,因为它具有 ( ) 然后它在其中调用 String 文字“hello”?

String s2 = "Goodbye"; 我认为这是一个字符串文字,因为字符串实际上是对象,所以字符串文字也被认为是对象。 不是 100% 确定这是不是真的。

String s3 = s1; 只是指回 s1。因此,它并不明显。

所以我的答案是 2 个不同的对象。

请解释我是对还是错。

【问题讨论】:

  • @YassinHajaj 不会是 3 个对象吗?字符串池中的两个(文字)和构造函数创建的另一个。
  • @YassinHajaj “字符串池中的一个” 哪个?由于他有两个文字,因此必须有人决定。
  • 我认为这只是一个基本的新手问题汤姆。当您说构造函数时,您的意思是“新的”,对吗?那是构造函数?字符串池是存储字符串内存的地方。我知道堆属于所有对象,那么字符串池是否是特定于字符串的堆的一部分?
  • 感谢科学。如果 "" 不在池中,不知道 new String("") 创建了两个对象。

标签: java instances


【解决方案1】:

正确答案是 3。

String s1 = new String("hello");
String s2 = "GoodBye";
String s3 = s1;

编译器会在编译期间将文本 "hello""GoodBye" 放入一个“常量池”,然后由类加载器加载。因此,当 JVM 加载该类时,它会自动实习该类使用的所有字符串文字。有关此的更多信息:When are Java Strings interned?。然后在运行时管理String constant pool

在运行期间,JVM 将在到达String s1 = new String("hello") 行时创建第三个 String 对象。

因此,您可以使用三个不同的 String 对象,其中两个包含相同的单词 "hello"。所以s1.equals("hello") 将是true,但s1 == "hello" 将是false,因为s1 引用堆上的不同字符串,而不是文字“hello”

String s3 = s1 行只是创建了一个变量s3,并复制了对s1 的String 对象的引用。它创建一个新对象。

另外请注意,您可以使用String#intern 方法“手动”将字符串添加到字符串常量池中。所以s1.intern() == "hello"true,因为从s1.intern() 返回的String 引用是对已经在常量池中的文字"hello" 的引用。

如果您想通过一些关于对象及其位置的图纸获得另一个可能更详细的说明,您可以查看this article on javaranch

【讨论】:

  • @sam2090(第一条评论):当您使用搜索引擎搜索类似问题时,您会看到很多用户对此感到困惑。所以不用担心:)。
  • 谢谢我收到了笔记。
  • @FooFighter 关于您对 fabian 的问题:这与我在回答中所写的含义相同:字符串 "hello" 是字符串文字,因此是堆上的对象. new String("hello")创建的String是another对象,但包含了同一个词,即hello
  • 不错的答案。我认为如果有一张漂亮的指向池和堆的引用图,这将是可以理解的。你不觉得吗?
  • @Tom 谢谢你的回答!如果我在概念上是正确的,那么 JVM 会从上到下运行。因此,它读取内部带有字符串文字的新字符串,并将 hello 发送到字符串常量池,然后读取真正的字符串文字 Goodbye,因此同样如此。然后当它读取第三行时,它分配新内存,因为它有一个新变量 s3 并复制 s1 的引用,但是这又会创建一个新对象,因为它是一个新变量?这是正确的吗?
猜你喜欢
  • 1970-01-01
  • 2022-11-12
  • 2019-04-24
  • 2014-12-27
  • 1970-01-01
  • 2021-11-24
  • 1970-01-01
  • 2012-09-04
  • 1970-01-01
相关资源
最近更新 更多