返回私有成员时,返回的值是对成员的直接引用还是单独的副本?

时间:2018-09-09 08:00:46

标签: java access-modifiers

为澄清这一点,请考虑以下代码:

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 变异修改从Object收到的foo.getThing()的值时,它是foo中的原始私有成员变异已修改?

编辑:一些单词

5 个答案:

答案 0 :(得分:0)

getThing()返回的内容是对私有变量thing

引用

如果需要修改,请使用foo.getThing().doSomeMethod()

您目前在changeThing中所做的事情:获取对foo事物的引用,并将其分配给方法变量thing。然后,将完全不同的内容分配给变量thing。这不会更改实例foo

中的任何内容

答案 1 :(得分:0)

是的,如果您实际上对对象进行了变异,则foo中的原始成员将被变异。当前,您只是在重新分配您持有的变量,该变量不会对该对象本身执行任何操作。

考虑这个

MPMusicPlayerController

答案 2 :(得分:0)

  

foo中的原始私有成员是否发生了变异?

否,因为您要为<video id="vidNew" class="video" controls="controls" poster="../new/image/happynewyear.png" src="../new/img/bye.mp4"> </video> 中的变量thing分配新内容,而不是使对象变异。如果您进行了突变,则该突变也会反映在私有成员中。

请注意,changeThing 返回由getThing引用的原始对象,不是它的副本。

由于在您的代码中,Foo.thing的类型为thing,因此这种行为很难看清。我将使用一个可变的类Object进行演示:

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的副本并返回(Java不会自动为您复制!),或者,
  • 使thing的类型不可变

答案 3 :(得分:0)

查看评论:

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

可能会造成混淆,因为您将两者都命名为“事物”。 e。在foo-object外部声明的对象事物和在foo-class内的对象变量“事物”。

重要的是对象和原始数据类型之间的区别,而对象变量或名称(例如“ 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都指向同一数据。

答案 4 :(得分:0)

首先,您应该了解引用类型的概念...

考虑以下代码: Foo f = new Foo();

这实际上是两个命令

1,新的foo()=>它在称为堆的内存中创建一个foo,它是您的实际var或content

2,Foo f =>将上面的var(content)地址放入f中。所以f是对内容的引用。

在您的代码中,当您返回此内容时,实际上,您返回的是对象的引用或地址。

以及您撰写时:

foo.getThing()返回Foo类中的东西,它是对象的引用或指针,然后是

对象事物= foo.getThing();

将Foo的东西的地址放在另一个名为Thing的引用中。 这意味着他们两个都指向相同的内容...