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

问题描述 投票:0回答:5

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

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中的原始私人成员 突变 改性?

编辑:有些话

java access-modifiers
5个回答
0
投票

foo中的原始私人成员是变异的吗?

不,因为你在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进行任何修改,您可以:

  • 手动创建thing的副本并将其返回(Java不会自动为您复制!)或者,
  • 使thing的类型不可变

0
投票

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

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

你目前在changeThing做什么:抓住对foos事物的引用并将其分配给方法变量thing。然后你赋予变量thing一个完全不同的东西。这不会改变实例foo中的任何内容


0
投票

是的,如果你实际改变了对象,foo中的原始成员就会发生变异。目前,您只需重新分配您持有的变量,该变量不会对对象本身执行任何操作。

考虑一下

public class Foo {
    private FooInner thing = new FooInner();

    public FooInner getThing() {
        return this.thing;
    }

    public String toString() {
        return Integer.toString(thing.i);
    }

    class FooInner{
        int i = 0;
    }


    public static void main(String[] args) {

        Foo foo = new Foo();

        System.out.println(foo); //Prints 0 

        FooInner thing = foo.getThing();
        thing.i = 10;

        System.out.println(foo); //Prints 10

    }
}

0
投票

首先,您应该了解参考类型的概念......

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

事实上,这是两个订单

1,new foo()=>它在一部分内存中创建了一个名为heap的foo,它是你真正的var或content

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

在你的代码中,当你返回this.thing,实际上,你返回一个对象的引用或地址。

当你写:

food.getTing()返回Foo类中的东西,它是一个对象的引用或指针然后

Object thing = for.getTing();

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


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

可能会有一种混乱,因为你将两者都命名为“东西”,即。即在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都指向相同的数据。

© www.soinside.com 2019 - 2024. All rights reserved.