Java对象分配

18 java object pass-by-reference variable-assignment

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

Test t1 = new Test();
Test t2 = t1;
t1.i=1;
Run Code Online (Sandbox Code Playgroud)

假设变量i的测试类中定义的,我说得对假设T1和T2点到修改同一个对象t1.i=1会影响t1t2?实际上我测试了它,看起来我是对的.但是,当我尝试相同的操作时String,修改仅发生在另一侧不受影响的一侧.这背后的原因是什么?

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

String s1 = "0";
String s2 = s1;          
s1 = "1";
System.out.println(s1);
System.out.println(s2);
Run Code Online (Sandbox Code Playgroud)

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

Tom*_*Tom 15

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

@newacct

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

注意:String类是不可变的,因此一旦创建,就无法更改String对象.String类有许多方法,其中一些将在下面讨论,它们似乎可以修改字符串.由于字符串是不可变的,因此这些方法真正做的是创建并返回包含操作结果的新字符串.

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

@ user1238193

考虑到你的以下问题:"测试T2 = T1,导致两个T1和T2指向同一对象或每个现在有自己的对象并没有这种情况适用于Java的所有对象?"

t1和t2将指向同一个对象.对于任何java对象都是如此(包括不可变对象)

  • 没有"特殊情况".对任何类型的引用的赋值都会更改它指向的对象,而不会影响它所指向的对象. (2认同)
  • 不,`String`恰好没有任何改变它的方法."试图改变它们"没有意义; 你不能"尝试"做一些不存在的事情.`String.replace`给你一个新对象 - 你有什么意义?这就是它的文档所说的.`Integer`和许多其他类是不可变的.通过将字段设为私有并且不提供任何方法来更改其字段,您可以轻松地编写一个不可变的类.在任何情况下,可变性与问题无关,最初的问题是关于改变`Test`上的字段,但`String`上没有公共字段. (2认同)
  • String 实习池与这个问题或可变性完全无关。任何类都可能有也可能没有像 String 这样的实习池 (2认同)

Nli*_*tis 5

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

Test t1 = new Test();
Run Code Online (Sandbox Code Playgroud)

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

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

Test t2 = t1;
Run Code Online (Sandbox Code Playgroud)

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

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

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

关于你的编辑:

String s1 = "0";
String s2 = s1;          
s1 = "1";
System.out.println(s1);
System.out.println(s2);
Run Code Online (Sandbox Code Playgroud)

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

s1 = "1";
Run Code Online (Sandbox Code Playgroud)

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


new*_*cct 5

在这两种情况下,您正在做完全不同的事情。在第一种情况下,使用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);
Run Code Online (Sandbox Code Playgroud)

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