Java对象分配

时间:2012-06-13 09:15:45

标签: java object pass-by-reference variable-assignment

我是Java新手,关于对象分配我有一些问题。例如,

Test t1 = new Test();
Test t2 = t1;
t1.i=1;

假设在Test类中定义了变量i,我是否正确假设t1和t2都指向修改t1.i=1同时影响t1和{{1}的同一对象}?实际上我测试了它,看起来我是对的。但是当我在t2上尝试相同的事情时,修改只发生在另一边不受影响的一侧。这背后的原因是什么?

编辑:我尝试使用String的情况。

String

我通过测试String上的案例来实现我的错误,因为它是不可变的。我认为String s1 = "0"; String s2 = s1; s1 = "1"; System.out.println(s1); System.out.println(s2); 修改字符串的情况实际上是将“1”的引用返回给s1。不过,我的问题仍然存在。 s1="1"是否会导致t2和t1指向同一个对象,或者每个都有自己的对象?这种情况是否适用于Java上的所有对象?

8 个答案:

答案 0 :(得分:14)

你是对的,但字符串是一个特例;在这种情况下,它们是不可变的,就像原始一样。

@newacct

我引用http://docs.oracle.com/javase/tutorial/java/data/strings.html

  

注意:String类是不可变的,因此一旦创建了它   字符串对象无法更改。 String类有一个数字   方法,其中一些将在下面讨论,似乎   修改字符串。由于字符串是不可变的,这些方法究竟是什么   do是创建并返回一个包含结果的新字符串   操作。

这就是使字符串成为特例的原因。如果您不知道这一点,您可能希望引用中讨论的方法不会返回新的字符串,这会导致意外的结果。

@ user1238193

考虑以下问题:“测试t2 = t1;导致t2和t1指向同一个对象,或者现在每个都有自己的对象吗?这种情况是否适用于Java上的所有对象?”

t1和t2将指向同一个对象。对于任何java对象(包括不可变对象)

都是如此

答案 1 :(得分:5)

你的第一个假设是正确的。使用以下代码行:

Test t1 = new Test();

您创建一个新的Test对象,同时创建一个名为t1的Test引用来引用它。

在您发布的代码的第二行:

Test t2 = t1;

您实际上正在创建另一个Test引用,并将其指定为引用t1引用的同一对象。

所以t1.i = 1;会影响t2.i,因为它毕竟是同一个对象。

对于字符串,字符串是不可变的,在实例化后无法修改。

关于你的编辑:

String s1 = "0";
String s2 = s1;          
s1 = "1";
System.out.println(s1);
System.out.println(s2);

他们会打印出不同的结果,因为当你真正说出

s1 = "1";

你实际上是将s1绑定到另一个String对象,但是s2仍然会引用值为“0”的对象。

答案 2 :(得分:3)

你是绝对正确的,因为t1和t2都指向同一个对象,对象状态中的任何chane都会影响到两者。

String是一个不可变对象。所以它根本无法修改。 see this了解有关java中不可变对象的更多信息。

答案 3 :(得分:2)

String objects are immutable


修改

Test t2 = t1;是否会导致t2和t1指向同一个对象,或者现在每个对象都有自己的对象?

是。虽然t2是一个新的引用,但它会指向同一个对象,因为你告诉它这样做。创建t2类型的新引用Test,并让它指向t1所指向的同一对象。

但是,当您使用String执行此操作然后执行s1 = "1" ;之类的操作时,您将使s1指向另一个String对象。你可以用s1 = new String(1);来区分它。

答案 4 :(得分:2)

在这两种情况下,你做的事情完全不同。在第一种情况下,使用t1.i = 1;,您正在修改t1指向的对象。在第二种情况下,使用t1 = "1";,您将更改引用指向另一个对象(类似于您t2 = t1;的时间。

如果对第二种情况中的Test做同样的事情,你会得到相同的结果(假设Test有一个带整数的构造函数):

Test t1 = new Test(5);
Test t2 = t1;          
t2 = new Test(1); // Here we are assigning to the variable, just like your 2nd example
System.out.println(t1);
System.out.println(t2);

人们提到String是不可变的。但这是无关紧要的,语言中没有“可变性”的概念,“可变”和“不可变”类的工作方式也没有区别。我们非正式地说一个类是“不可变的”,如果它碰巧没有你可以设置的任何字段或任何可以改变其内部内容的方法。 String就属于这种情况。但是如果你根本不做任何改变它的话,一个可变类会以完全相同的方式工作。

答案 5 :(得分:1)

String就像任何其他对象一样。因此,您指定的任何变量都指向对象的同一实例,就像您对测试对象所做的那样。

但请记住,String没有你可以像在Test上那样设置的字段,所以你基本上不能做同样的测试,所以没有办法将你的代码从Test对象移植到String对象。

使用基本类型(如long,int等)可以获得相反的行为。 它们被“按值”分配给变量,所以如果你这样做了

int t1 = 12;
int t2 = t1;
t1=15;

t2仍有值12

答案 6 :(得分:0)

以StringBuilder为例,会更清晰一些。以下示例显示了仅使用引用而不是值的对象分配。

{ StringBuilder str = new StringBuilder();

    str.append("GFG");

    StringBuilder str1 = str;

    str.append("tail");
    // output: str1 = GFGtail str = GFGtail
    System.out.println("str1 = " + str1.toString() + " str = " + str.toString());  

}

答案 7 :(得分:0)

因为java使用字符串文字的概念。假设有5个参考变量,所有参考变量都指向一个对象“ 0”。如果一个参考变量更改了该对象的值,它将影响所有参考变量。这就是为什么字符串对象在Java中是不可变的。