通过价值或参考

时间:2013-12-24 22:28:25

标签: java reference

我知道这个话题非常好,但是......

我正在为java编写一个Android应用程序,但我来自c ++,其中值或引用的问题非常明确。 问题是:

最初我有一个名为 Item 的类,它有一个变量 public int ID

在名为 ListingItem 的类中,我有一个静态列表列表,其中添加了两个,每个都已分配给其变量< strong> ID 值 1 。在此课程中还有一个函数公共静态列表getList(),它返回列表,特别是此类的列表列表

在另一个名为 Fragment 的课程中,我有一个 List ItemList 和一个返回列表的函数私人列表getList()

Fragment类的 getList()执行以下操作:

private List <Item> getList()
{
    List<Item> list = ListingItem.getList() // copy list from ListingItem.list
    List<Item> returnList = new ArrayList<Item>();

    returnList.add(list.get(0);
    returnList.add(list.get(1); // copy to returnList two Item objects from list (that copied from ListingItem.list)

    returnList return;
}

Fragment 的另一个功能是使用 Fragment.getList(),如下所示:

private functionOfFragment()
{
    List<Item> ItemList = getList();

    itemList.get(0).ID = 2;
    itemList.get(1).ID = 2; // changing from 1 to 2
}

但是, ListingItem.list.get(0).ID ListingItem.list.get(0).ID 的值也是值 2 即可。这怎么可能?

obs:这个代码只是代表,问题不是SYNTAX错误!

4 个答案:

答案 0 :(得分:3)

在Java中,传递值与引用也是非常明确的。对于一切,只有价值传递。

在您的示例中,您从Item检索ArrayList个实例,并将引用的副本传递给returnList.add。尽管如此,副本指向内存中与原始文件相同的对象,并且它们都可以通过点运算符“解除引用”。

当你说itemList.get(1).ID = 2时,这就是你在做什么。因为ID是公共的,所以当您取消引用时,您正在访问该对象并将其值设置为新的值。

因此,对对象(以及基元)的引用按值传递,但它们引用的对象可以按类API定义的方式进行更改。这与传递引用不同,在管理内存的语言中这是不可行的。

答案 1 :(得分:2)

因为变量引用相同的指示物。每个java.lang.Object(例如,对象不是基元)变量的值是参考地址(例如“令人困惑的”默认toString()实现),我希望有所帮助!此外,这是向后returnList return;

答案 2 :(得分:2)

Java中的值传递参数与C ++中的不一样。

在Java中:

  • 参数传递总是值。
  • 对象引用本身就是一个变量,用于存储对象的位置。
  • 传递对象引用传递其值

因此,Java中的对象引用在功能上与类似指针,但您无法取消引用并重新分配它。

在C ++中你可以这样做:

#include <iostream>

class SomeObj {
public:
    int num;
    SomeObj(int n) {
        num = n;
    }
};

void reassign(SomeObj* obj) {
    *obj = *(new SomeObj(5));
}

int main(int argc, char* const argv[]) {
    SomeObj* obj = new SomeObj(0);

    reassign(obj);

    // prints '5'
    std::cout << obj->num << std::endl;

    return 0;
}

你不能用Java做到这一点。 Java引用变量不是C ++指针,不是C ++引用,也不是C ++对象值。

你只能这样做:

void reassignLocal(SomeObj* obj) {
    obj = new SomeObj(5);
}

而且:

void mutateElsewhere(SomeObj* obj) {
    obj->num = 5;
}

所以创建一个新的List,如下所示:

static List<SomeObj> shallowCopy(List<SomeObj> input) {
    List<SomeObj> output = new ArrayList<SomeObj>(input.size());

    for (SomeObj obj : input)
        output.add(obj);

    return output;
}

仅将引用从一个列表复制到另一个列表。它们是相同的对象。变异output元素将改变input个元素,反之亦然。要更改它,您需要实际实例化新对象。

static List<SomeObj> deepCopy(List<SomeObj> input) {
    List<SomeObj> output = new ArrayList<SomeObj>(input.size());

    for (SomeObj obj : input)
        output.add(new SomeObj(obj.num));

    return output;
}

答案 3 :(得分:1)

我想在Java中我们“按值传递引用”,当然除了原语之外。在原语的情况下,它们本身就是通过值传递的。