繁体   English   中英

Java返回值,对象引用

[英]Java return value, object references

我已经阅读了Jon Skeet的[优秀]文章,内容涉及在Java中传递值,并且在同一主题上看到了这个问题 我相信我理解它们,但是我仍然想知道的是返回值。

当一个对象被返回时(例如从一个吸气剂中返回),然后在其原始范围(从中获取它)中进行了更改,该对象引用被该获取器的返回值分配给的变量所拥有吗? 满口的男孩..
举一个例子:

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);
    }
}

那会打印RoverMax吗?

UPDATE是否打印流动站。

我最初的问题的答案很好,但理查德·廷格(Richard Tingle)在下面的评论中添加了很多有用的信息,因此我认为我将为后代提供测试课程。

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));
}

输出为falsefalsetruefalse

它将打印流动站一次。

原因:

 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 :)
    }

是否打印Rover或Max?

它将打印Rover

因为,您已经从该Dog对象中检索了该值。 稍后更改为Dog对象myDog ,不会影响变量dogName的值

当一个对象被返回时(例如从一个吸气剂中返回),然后在其原始范围(从中获取它)中进行了更改,该对象引用被该获取器的返回值分配给的变量所拥有吗?

不,它不会更改您分配的参考。 因为您已经获取了值。

如许多答案所述,将打印“ Rover”,因为您已经更改了dog的实际字符串。 您尚未更改String本身(由于String是不可变的,又称为不可更改的,因此您无法执行此操作)。

public static void main(String args[])
{
    Dog myDog = new Dog("Rover"); //myDog contains STRING1 ("Rover")
    String dogName = myDog.getName(); //dogName is set to refer to STRING1 ("Rover")
    myDog.setName("Max"); //myDog name set to STRING2 ("Max") (STRING1 unaffected)
    System.out.println(dogName); //dogName still refers to STRING1 ("Rover"), "rover" printed
}

更一般的概念

这可能给人的印象是,一旦使用吸气剂从另一个对象检索内部对象,它就完全独立了,您可以根据需要进行更改。 并非总是如此。 字符串是不可变的,因此您无法更改其内部状态。 但是,如果您访问了一个可变的对象(也可以更改)并且在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

    }

}

如您所见,如果您检索arrayList然后向其添加对象,这将影响Dog中的ArrayList。 如果您检索arrayList并将变量设置为完全不同的ArrayList,则这不会影响Dog中的arrayList(因为它的数组ArrayList不同)。 将对象视为“没有特别的地方”,并将变量寻址到这些对象。

如此类推; 您( Dog对象)有一个您关心的房屋(其他对象)的通讯录。 您可以将地址簿更改为指向另一所房子,没有人会在意。 但是,如果您给房屋写封信说“将门漆成绿色”,那么其他人都将注意到该房屋。

一般规则是,如果您更改变量以使其仅指向更改的其他对象(例如更改地址簿中的地址),则该变量始终包含=且可能包含new变量(但可能不包含new变量,而新变量被隐藏)与字符串)。 在另一方面,如果你使用的方法的对象(如寄送包裹的房子,你有一个地址),然后到处都是那个对象是可见的将看到的变化(这总是涉及.到这是一个setter方法(或者更改对象,例如add

这将是Rover,因为在Dog对象中,您只是将引用从一个String对象(“ Rover”)更改为另一个(“ Max”),但是dogName仍引用“ Rover”。 顺便说一句,您应该自己运行代码。

通过做这个:

String dogName = myDog.getName();  

您正在创建一个新的String对象,其中包含“ Rover”,该对象未引用对象myDog中的属性dog:它们是完全独立的。
因此,当您修改myDog的dog值时,此更改不会影响变量“ dogName”

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM