Java返回值,对象引用

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.

我读过Jon Skeet关于Java中传递值的文章,也看到过关于同一主题的文章。我相信我理解他们,但我仍然是 想知道的是返回值

当一个对象被返回(比如从一个getter中),然后在它的原始作用域中被改变(它是从哪里得到的)时,这个对象引用是否被赋予getter返回值的变量所拥有?男孩,那是一口….
借用一个例子:

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

    }

}