4

我是 Java 新手,并且已经阅读了我所相信的相互矛盾的陈述。请考虑以下代码。

String str1 = "dave";
String str2 = "dave";

str1 和 str2 虽然是唯一变量,但引用完全相同的值。那么,在内存中创建了多少个独特的对象?1或2,有人可以解释为什么吗?

4

5 回答 5

14

在您的示例中,它们引用同一个对象,因为字符串是interned

通常,使用new创建新对象,因此使用:

String str1 = new String("dave");
String str2 = new String("dave");

将在堆中创建两个不同的对象。

于 2013-03-15T13:50:23.433 回答
10

没那么复杂。除非你在谈论字符串;-)

首先,让我们忽略字符串并假设这个简单的类型:

public class ValueHolder {
  private final int value;

  public ValueHolder(int value) {
    this.value = value;
  }

  public int getValue() {
    return value;
  }
}

如果你有这样的两行:

ValueHolder vh1 = new ValueHolder(1);
ValueHolder vh2 = new ValueHolder(1);

那么您将在堆上创建恰好 2 个对象。即使它们的行为完全相同并且在其中存储了完全相同的值(并且无法修改),您仍将拥有两个对象。

所以vh1 == vh2会回来的false

对象也是如此:可以存在String两个String具有相同值的对象。

但是,有一件具体的事情String:如果您在代码中使用String文字(*),Java 将尝试重新使用任何较早出现的这种情况(通过称为interning的过程)。

因此,在您的示例代码中str1str2 将指向同一个对象

(*)或更准确地说:类型的编译时常量表达式String

于 2013-03-15T13:49:22.990 回答
9

您有一个唯一的Object和 2 个指向同一对象的引用。这是String池化(或实习)的结果。鉴于两个String文字具有相同的内容,确保可以创建2 个单独 的唯一方法是显式调用其中一个构造函数。ObjectsString

于 2013-03-15T13:49:14.757 回答
0

这取决于。如果您编写一个小测试程序,那么它们很有可能包含相同的引用,因为 java 试图通过节省内存和重用引用来帮您一个忙。如果 str2 来自用户输入,那么它可能是两个不同的引用。一个很好的测试方法是在比较中使用 == 。如果两者是 ==,那么它们引用的是相同的内存位置。如果不是,那么它们是两个不同的参考。这让很多初级程序员望而却步,因为当他们第一次开始编写代码时,他们使用 ==,看到它有效,然后无法弄清楚为什么他们的比较不起作用。

我无法具体解释java何时“在幕后”重用引用,但它与创建值的方式和时间有关

于 2013-03-15T13:51:17.950 回答
0

你正在写这个的简写版本

String str1 = new String("dave");
String str2 = new String("dave");

所以 str1 和 str2 是不同的对象,可以单独修改

原始字符串“dave”仅在内存中存在一次,并带有另一个引用。

于 2013-03-15T13:53:40.587 回答