返回私有成员时,返回值是对该成员的直接引用还是单独的副本?
When returning a private member, is the returned value a direct reference to the member or a separate copy?
为了阐明这一点,请考虑以下代码:
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
mutates修改了从foo.getThing()
接收到的Object
的值时,是[=14中的原始私有成员=] 突变 修改?
编辑:一些话
getThing()
返回的东西是对私有变量thing
的引用
如需修改,使用foo.getThing().doSomeMethod()
您目前在 changeThing
中所做的事情:获取对 foo
的引用并将其分配给方法变量 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
}
}
is the original private member within foo mutated?
不,因为您正在为 changeThing
中的变量 thing
分配一些新内容,而不是改变对象。如果您确实改变对象,改变也会反映在私有成员中。
注意getThing
将 return Foo.thing
引用的原始对象,不是它的副本。
由于在您的代码中,thing
属于 Object
类型,因此很难看到此行为。我将使用可变 class 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
的副本并 return 它(Java 不会自动为您复制!)或者,
- 使
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();
}
}
可能会造成混淆,因为您将两者都命名为 "thing",我。 e.在 foo-object 外声明的对象 thing 和在 foo-class.
内声明的对象变量 "thing"
重要的是对象和原始数据类型之间的区别,而对象变量或名称如 "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 都指向相同的数据。
首先,你应该了解引用类型的概念...
考虑以下代码:
Foo f = new Foo();
事实上,这是两个订单
1, new foo() => 它在称为堆的内存部分创建一个 foo,它是你真正的 var 或内容
2, Foo f => 上面的var(content)地址放在f中。所以 f 是对内容的引用。
在您的代码中,当您 return this.thing 时,实际上,您 return 一个对象的引用或地址。
当你写的时候:
foo.getThing() return Foo class 中的东西,它是一个对象的引用或指针,然后
对象东西=foo.getThing();
将 Foo 的地址放在另一个名为 thing 的引用中。
这意味着它们都指向相同的内容...
为了阐明这一点,请考虑以下代码:
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
mutates修改了从foo.getThing()
接收到的Object
的值时,是[=14中的原始私有成员=] 突变 修改?
编辑:一些话
getThing()
返回的东西是对私有变量thing
如需修改,使用foo.getThing().doSomeMethod()
您目前在 changeThing
中所做的事情:获取对 foo
的引用并将其分配给方法变量 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
}
}
is the original private member within foo mutated?
不,因为您正在为 changeThing
中的变量 thing
分配一些新内容,而不是改变对象。如果您确实改变对象,改变也会反映在私有成员中。
注意getThing
将 return Foo.thing
引用的原始对象,不是它的副本。
由于在您的代码中,thing
属于 Object
类型,因此很难看到此行为。我将使用可变 class 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
的副本并 return 它(Java 不会自动为您复制!)或者, - 使
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();
}
}
可能会造成混淆,因为您将两者都命名为 "thing",我。 e.在 foo-object 外声明的对象 thing 和在 foo-class.
内声明的对象变量 "thing"重要的是对象和原始数据类型之间的区别,而对象变量或名称如 "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 都指向相同的数据。
首先,你应该了解引用类型的概念...
考虑以下代码: Foo f = new Foo();
事实上,这是两个订单
1, new foo() => 它在称为堆的内存部分创建一个 foo,它是你真正的 var 或内容
2, Foo f => 上面的var(content)地址放在f中。所以 f 是对内容的引用。
在您的代码中,当您 return this.thing 时,实际上,您 return 一个对象的引用或地址。
当你写的时候:
foo.getThing() return Foo class 中的东西,它是一个对象的引用或指针,然后
对象东西=foo.getThing();
将 Foo 的地址放在另一个名为 thing 的引用中。 这意味着它们都指向相同的内容...