Java 如果我有两个引用类型,具有相同的值,这是否意味着内存中只有一个对象

Java 如果我有两个引用类型,具有相同的值,这是否意味着内存中只有一个对象,java,pointers,Java,Pointers,我是Java新手,读过一篇与我所相信的相矛盾的陈述。请考虑以下代码。 String str1 = "dave"; String str2 = "dave"; str1和str2虽然是唯一的变量,但引用的值完全相同。那么,在内存中创建了多少个独特的对象?1或2,有人能解释为什么吗 您有一个唯一的对象&2个指向同一对象的引用。这是由于Stringpooling(或interning)造成的。考虑到两个String文本具有相同的内容,确保可以创建两个独立的对象的唯一方法是显式调用一个String构造

我是Java新手,读过一篇与我所相信的相矛盾的陈述。请考虑以下代码。

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

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

您有一个唯一的
对象
&2个指向同一对象的引用。这是由于
String
pooling(或interning)造成的。考虑到两个
String
文本具有相同的内容,确保可以创建两个独立的
对象的唯一方法是显式调用一个
String
构造函数。除非你说的是字符串;-)

首先,让我们忽略字符串并假设以下简单类型:

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
对象

然而关于
字符串
,有一点是特别的:如果在代码中使用
字符串
文本(*),Java将尝试重新使用任何早期出现的字符串(通过一个名为

因此,在您的示例中,code
str1
str2
将指向同一个对象


(*)或者更准确地说:a。

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

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

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

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

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


我无法具体解释java何时会在“幕后”重用引用,但它与如何以及何时创建值有关

String str1 = new String("dave");
String str2 = new String("dave");
因此,str1和str2是不同的对象,可以单独修改


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

试一试怎么样?打开Java,运行代码后打印它们的引用……看看这是否意味着,如果我更改了str1,str2的值也会更改,因为它们指向同一位置?不能更改
str1
(除非通过反射),因为
字符串
是不可变的。但是,您可以将引用更改为指向不同的
字符串。在这种情况下,另一个引用的值不受影响。因此,如果稍后我执行str1=“dave2”,它实际上会生成一个新的字符串对象“dave2”,并对“dave2”的对象进行str1引用?@cwhsu:没错!(虽然“创建新字符串对象”可以替换为“将正确的字符串对象从内部字符串池中取出”,但如果以前某个地方已经需要了
“dave2”
。@cwhsu它只会创建一个新的
字符串,但池中还没有匹配的字符串。这是一个解释得很好的答案,有一个非常有用的链接。谢谢。+1:好的一般说明:使用
new
总是创建一个新对象。