Java 如果我有两个引用类型,具有相同的值,这是否意味着内存中只有一个对象
我是Java新手,读过一篇与我所相信的相矛盾的陈述。请考虑以下代码。Java 如果我有两个引用类型,具有相同的值,这是否意味着内存中只有一个对象,java,pointers,Java,Pointers,我是Java新手,读过一篇与我所相信的相矛盾的陈述。请考虑以下代码。 String str1 = "dave"; String str2 = "dave"; str1和str2虽然是唯一的变量,但引用的值完全相同。那么,在内存中创建了多少个独特的对象?1或2,有人能解释为什么吗 您有一个唯一的对象&2个指向同一对象的引用。这是由于Stringpooling(或interning)造成的。考虑到两个String文本具有相同的内容,确保可以创建两个独立的对象的唯一方法是显式调用一个String构造
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将尝试重新使用任何早期出现的字符串(通过一个名为
因此,在您的示例中,codestr1
和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
总是创建一个新对象。