为了澄清这一点,请考虑以下代码:
public class Foo {
private Object thing;
public Foo() { ... }
public Object getThing() {
return this.thing;
}
}
public class Bar {
public Bar() { ... }
public Object makeNewThing() { ... }
public void changeThing() {
Foo foo = new Foo();
Object thing = foo.getThing();
thing = makeNewThing();
}
}
当Bar
变异
修改它从Object
收到的foo.getThing()
的值,是foo
中的原始私人成员
突变
改性?
编辑:有些话
foo中的原始私人成员是变异的吗?
不,因为你在thing
中为变量changeThing
分配了一些新东西,而不是改变对象。如果您确实改变了对象,则突变也会反映在私有成员中。
请注意,getThing
将返回Foo.thing
引用的原始对象,而不是它的副本。
因为在你的代码中,thing
的类型为Object
,所以这种行为有点难以察觉。我将使用一个可变类Baz
来演示这个:
public class Baz {
public int x = 0;
}
public class Foo {
private Baz thing;
public Foo() { thing = new Baz(); }
public Baz getThing() {
return this.thing;
}
}
public class Bar {
public Bar() { ... }
public Object makeNewThing() { ... }
public void changeThing() {
Foo foo = new Foo();
Baz thing = foo.getThing();
thing.x = 10;
System.out.println(foo.thing); // this will print 10, not 0
}
}
因此,为避免对Foo.thing
进行任何修改,您可以:
thing
的副本并将其返回(Java不会自动为您复制!)或者,thing
的类型不可变getThing()
返回的内容是对私有变量thing
的引用
如果您需要修改它,请使用foo.getThing().doSomeMethod()
你目前在changeThing
做什么:抓住对foo
s事物的引用并将其分配给方法变量thing
。然后你赋予变量thing
一个完全不同的东西。这不会改变实例foo
中的任何内容
是的,如果你实际改变了对象,foo中的原始成员就会发生变异。目前,您只需重新分配您持有的变量,该变量不会对对象本身执行任何操作。
考虑一下
public class Foo {
private FooInner thing = new FooInner();
public FooInner getThing() {
return this.thing;
}
public String toString() {
return Integer.toString(thing.i);
}
class FooInner{
int i = 0;
}
public static void main(String[] args) {
Foo foo = new Foo();
System.out.println(foo); //Prints 0
FooInner thing = foo.getThing();
thing.i = 10;
System.out.println(foo); //Prints 10
}
}
首先,您应该了解参考类型的概念......
考虑以下代码:Foo f = new Foo();
事实上,这是两个订单
1,new foo()=>它在一部分内存中创建了一个名为heap的foo,它是你真正的var或content
2,Foo f =>上面的var(内容)地址放在f中。所以f是对内容的引用。
在你的代码中,当你返回this.thing,实际上,你返回一个对象的引用或地址。
当你写:
food.getTing()返回Foo类中的东西,它是一个对象的引用或指针然后
Object thing = for.getTing();
把Foo的东西的地址放在另一个名为thing的引用中。这意味着它们都指向相同的内容......
看评论:
public class Foo {
private Object thing;
//constructor to create an Foo-Object-Instance
public Foo() { ... }
//method to return a characteristic of a Foo-Object,
//whereas this characteristic is an object, not a primitive data type
public Object getThing() {
return this.thing;
}
}
public class Bar {
//constructor to create an Bar-Object-Instance
public Bar() { ... }
//returns an object and does whatever it's supposed to do within the { ... }
//I wonder how's object connected to bar?
public Object makeNewThing() { ... }
public void changeThing() {
//is Foo a subtype of Bar?
//creating a Foo-Class-Instance (object)
//that contains a variable Object (which is not the data as it would be with
//primitive data types, but a reference to the data)
Foo foo = new Foo();
//and with "foo.getThing()" you get the reference ("address")
//of the Object foo's characteristic "thing" (which is an object
//as well, so you copy the address to the data) and add it to the
//new "Object thing", which
//you have declared on the left side of the =
//so you have two object variables pointing/with reference to the same data
Object thing = foo.getThing();
//when you use makeAnewThing - whatever stands in there - to change the
//object ("thing") variables data, then the data of the object will
//be changed if so stated in the { } and
//hence basically the thing-object (or "variable")
//within the foo-object as well,
//because both variable names are pointing to the same data
thing = makeThing();
}
}
可能会有一种混乱,因为你将两者都命名为“东西”,即。即在foo-object之外声明的对象事物和foo-class中的对象变量“事物”。
重要的是对象和原始数据类型之间的区别,而对象变量或名称如“String objectname”或“Object foo”包含对数据的引用:
//declare an object named abs, which does not point to data
Object abc;
//declare an object named def and (right side of =) initiate it with data or variable or whatever the constructor says what's to be done
Object def = new Object();
//copy the reference ("address" of def-Object) to abc
abc = def;
//now we have one data thingi with two references to it, i. e. abc and def
如果您现在向abc添加更改,那么当在方法中声明时,更改将被添加到指向的数据abc中。如果您使用def.getData()之类的东西,则会返回更改的数据,因为abc和def都指向相同的数据。