Java返回值,对象引用
我读过Jon Skeet关于Java中传递值的文章,也看到过关于同一主题的文章。我相信我理解他们,但我仍然是 想知道的是返回值 当一个对象被返回(比如从一个getter中),然后在它的原始作用域中被改变(它是从哪里得到的)时,这个对象引用是否被赋予getter返回值的变量所拥有?男孩,那是一口….Java返回值,对象引用,java,return-value,scope,return-type,Java,Return Value,Scope,Return Type,我读过Jon Skeet关于Java中传递值的文章,也看到过关于同一主题的文章。我相信我理解他们,但我仍然是 想知道的是返回值 当一个对象被返回(比如从一个getter中),然后在它的原始作用域中被改变(它是从哪里得到的)时,这个对象引用是否被赋予getter返回值的变量所拥有?男孩,那是一口…. 借用一个例子: public class Dog { String dog ; public String getName() { return this.
借用一个例子:
public class Dog {
String dog ;
public String getName()
{
return this.dog;
}
public Dog(String dog)
{
this.dog = dog;
}
public void setName(String name)
{
this.dog = name;
}
public static void main(String args[])
{
Dog myDog = new Dog("Rover");
String dogName = myDog.getName();
myDog.setName("Max");
System.out.println(dogName);
}
}
打印的是Rover还是Max
更新
罗孚印刷公司
我最初问题的答案很好,但是理查德·丁格尔在下面的评论中添加了很多有用的信息,所以我想我应该为后代提供我的测试课程
public class Foo {
private ArrayList<Integer> arrayList;
public Foo() {
arrayList = new ArrayList<Integer>();
arrayList.add(1);
arrayList.add(2);
arrayList.add(3);
}
public ArrayList<Integer> getArrayList() {
return arrayList;
}
public void addToArrayList(int item) {
arrayList.add(item);
}
public static void main(String args[]) {
Foo foo = new Foo();
ArrayList<Integer> arrayList = foo.getArrayList();
ArrayList<Integer> cloneList = (ArrayList<Integer>)foo.getArrayList().clone();
System.out.println(arrayList.contains(4));
System.out.println(cloneList.contains(4));
foo.addToArrayList(4);
System.out.println(arrayList.contains(4));
System.out.println(cloneList.contains(4));
}
公共类Foo{
私有ArrayList ArrayList;
公共食物({
arrayList=新的arrayList();
arrayList.add(1);
arrayList.add(2);
arrayList.add(3);
}
公共ArrayList getArrayList(){
返回数组列表;
}
公共无效addToArrayList(整数项){
arrayList.add(项目);
}
公共静态void main(字符串参数[]){
Foo-Foo=新的Foo();
ArrayList ArrayList=foo.getArrayList();
ArrayList克隆列表=(ArrayList)foo.getArrayList().clone();
System.out.println(arrayList.contains(4));
System.out.println(cloneList.contains(4));
foo.addToArrayList(4);
System.out.println(arrayList.contains(4));
System.out.println(cloneList.contains(4));
}
输出为false
,false
,true
,false
那印的是罗孚还是马克斯
它将打印Rover
因为,您已经从该Dog
对象中检索到了值。稍后切换到Dog
对象myDog
,将不会影响变量dogName
的值
当一个对象被返回时(比如从一个getter返回),然后在
它的原始范围(从中获取)是对象引用
属于分配了getter返回值的变量
改变
不,它不会更改您分配的引用。因为您已经检索到了值。它将是Rover,因为在Dog对象中,您刚刚将引用从一个字符串对象(“Rover”)更改为另一个(“Max”),但dogName仍然引用“Rover”。顺便说一句,您应该自己运行代码。它将打印Rover一次 原因:
public void setName(String name)
{
this.dog = name;
}
public static void main(String args[])
{
Dog myDog = new Dog("Rover");
String dogName = myDog.getName(); // here you are setting dogName to rover
myDog.setName("Max"); // Here you are setting the String field of a Dog object to "Max" (just reassigning the reference and making it point to Max"
System.out.println(dogName); // DogName is still Rover.
// do dogName = myDog.getName(); and print it.. And see what happens :)
}
通过这样做:
String dogName = myDog.getName();
您正在创建一个包含“漫游者”的新字符串对象,该对象未引用对象myDog中的属性dog:它们完全独立。因此,当您修改myDog的dog值时,此更改不会影响变量“dogName”,正如许多答案所述,“Rover”将被打印,因为您已经更改了
dog
中的实际字符串。您还没有更改字符串本身(因为字符串是不可变的,也就是不可更改的),因此无法执行此操作
更一般的概念
这可能给人的印象是,一旦使用getter从另一个对象检索内部对象,它就完全是独立的,您可以根据需要对其进行更改。情况并非总是如此。字符串是不可变的,因此您无法更改其内部状态。但如果您访问的对象是可变的(aka可以更改)并在Dog
对象外部更改了其内部状态,那么它仍然会影响Dog
对象的内部状态。我将使用ArrayList
来显示此概念
public class Dog {
public ArrayList<String> names=new ArrayList<String>();
public ArrayList<String> getNames() {
return names;
}
public void setNames(ArrayList<String> names) {
this.names = names;
}
public static void main(String[] args){
Dog dog=new Dog();
dog.getNames().add("Rover");
ArrayList<String> someArrayList=dog.getNames();
someArrayList.add("Rex");
System.out.println(dog.getNames().contains("Rex")); //prints true. dog's internal state effected from afar
someArrayList=new ArrayList<String>(); //change someArrayList to refer to a whole new ArrayList
someArrayList.add("bad");
System.out.println(dog.getNames().contains("bad")); //prints false, someArrayList now points to a different ArrayList to the one internal to dog
}
}
公共级狗{
public ArrayList name=new ArrayList();
公共ArrayList getNames(){
返回姓名;
}
公共无效集合名(ArrayList名称){
this.names=名称;
}
公共静态void main(字符串[]args){
狗=新狗();
dog.getNames().add(“Rover”);
ArrayList someArrayList=dog.getNames();
someArrayList.添加(“Rex”);
System.out.println(dog.getNames().contains(“Rex”);//打印true。狗的内部状态从远处影响
someArrayList=new ArrayList();//更改someArrayList以引用一个全新的ArrayList
添加(“坏”);
System.out.println(dog.getNames().contains(“bad”);//prints false,someArrayList现在指向与dog内部不同的ArrayList
}
}
如您所见,如果检索arrayList并向其中添加对象,则会影响Dog中的arrayList。如果检索arrayList并将变量设置为完全不同的arrayList,则不会影响Dog中的arrayList(因为它是不同的arrayList)。将对象视为“无特定位置”以及被寻址到这些对象的变量
打个比方,你(一只狗)有一个你关心的房子(其他物体)的地址簿。你可以把你的地址簿改成指向另一所房子,没有人会在意。但是如果你给一所房子发了一封信,说“把门漆成绿色”,其他有地址的人都会注意到
一般规则是,如果您更改一个变量以指向不同的对象,则该变量只会更改(如更改通讯簿中的地址),这始终涉及
=
,并且可能涉及新的
(但可能不涉及,并且新的是用字符串隐藏的)。另一方面,如果您对对象使用方法(就像将包裹发送到你有地址的房子)然后无论在哪里都可以看到该对象的变化(这总是涉及到对setter方法的
(或以其他方式更改对象,如添加
))运行该代码并查看结果如何?String
无论如何都是不可变的。因此dogName
仍然是Rover
我认为这个问题不应该被高估,特别是当OP可以轻松运行代码时
public class Dog {
public ArrayList<String> names=new ArrayList<String>();
public ArrayList<String> getNames() {
return names;
}
public void setNames(ArrayList<String> names) {
this.names = names;
}
public static void main(String[] args){
Dog dog=new Dog();
dog.getNames().add("Rover");
ArrayList<String> someArrayList=dog.getNames();
someArrayList.add("Rex");
System.out.println(dog.getNames().contains("Rex")); //prints true. dog's internal state effected from afar
someArrayList=new ArrayList<String>(); //change someArrayList to refer to a whole new ArrayList
someArrayList.add("bad");
System.out.println(dog.getNames().contains("bad")); //prints false, someArrayList now points to a different ArrayList to the one internal to dog
}
}