Java返回值,对象引用

时间:2014-04-30 08:32:17

标签: java return-value scope return-type

我已经阅读了Jon Skeet的[excellent] article关于在Java中传递值并在同一主题上看到this question的信息。我相信我理解他们但我仍然是 想知道的是回报值。

当一个对象被返回时(来自一个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。

我原来问题的答案很棒,但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

5 个答案:

答案 0 :(得分:6)

它会打印一次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 :)
    }

答案 1 :(得分:3)

  

是否打印Rover或Max?

它将打印Rover

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

的值
  

当一个对象被返回时(来自一个getter)然后被改变了   它的原始范围(它来自哪里)是对象引用   由赋予getter返回值的变量所拥有   改变?

不,它不会改变您指定的参考。因为您已经检索了该值。

答案 2 :(得分:2)

正如许多答案所述,&#34; Rover&#34;将打印,因为您已更改dog内的实际字符串。你还没有改变字符串本身(你不能这样做,因为字符串是不可变的,也就是不可改变的。)

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
}

更一般的概念

这可能会给人一种印象,即一旦使用getter从另一个对象中检索内部对象,它就完全是独立的,您可以根据需要进行更改。事情并非总是如此。字符串是不可变的,因此您无法更改其内部状态。但是,如果您访问了一个可变的对象(也就是可以更改)并在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)。把对象想象为&#34;没有特别的地方&#34;以及针对这些对象的变量。

这么类比;你(一个Dog对象)有一个你关心的房屋的地址簿(其他对象)。您可以将地址簿更改为指向其他房屋,其他任何人都不会关心。但是,如果你给一个房子发一封信,说#34;把门涂成绿色的&#34;有房子地址的其他人都会注意到。

一般规则是,如果您更改变量以指向另一个对象,只更改变量(例如更改地址簿中的地址),这总是涉及=并且可能涉及{{1 (但可能没有,新的用字符串隐藏)。另一方面,如果您在对象上使用方法(例如将包裹发送到您拥有地址的房屋),那么该对象可见的任何地方都会看到更改(这总是涉及方法的new这是一个setter(或以其他方式更改对象,如.))

答案 3 :(得分:0)

它将是Rover,因为在Dog对象中,您只是将引用从一个String对象(&#34; Rover&#34;)更改为另一个(&#34; Max&#34;),但dogName仍引用& #34;流动站&#34 ;.顺便说一句,你应该自己运行代码。

答案 4 :(得分:0)

通过这样做:

String dogName = myDog.getName();  

您正在创建一个新的String对象,其中包含&#34; Rover&#34;它没有引用对象myDog中的属性dog:它们是完全独立的 因此,当您修改myDog的狗值时,此更改不会影响变量&#34; dogName&#34;