繁体   English   中英

通过值或参考传递

[英]Pass by value or reference

我知道这个主题很残酷,但是...

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

最初,我有一个名为Item的类,该类具有可变的public int ID

在一个称为ListingItem的类中,我有一个静态列表列表 ,其中添加了两个项目 ,每个项目都为其变量ID分配了值1 在此类中,还有一个函数public static List getList() ,它返回List ,特别是此类的List 列表

在另一个名为Fragment的类中,我有一个List ItemList和一个返回List的 私有list 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).IDListingItem.list.get(0).ID的值也是值2 这怎么可能?

obs:此代码仅是代表性的,问题不是语法错误!

在Java中,按值传递与引用传递也非常明确。 只有通过价值传递-一切。

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

这就是您说itemList.get(1).ID = 2时所做的事情。 由于ID是公共的,因此在取消引用时,您将访问该对象并将其值设置为新值。

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

因为变量引用相同的引用对象。 每个java.lang.Object (例如,对象不是原始对象)变量的值都是引用地址(例如,“令人困惑”的默认toString()实现),希望对您有所帮助! 同样,这是向后的returnList return;

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

因此,创建一个如下所示的新列表:

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

我要说的是,在Java中,我们“按值传递引用”,当然是原语除外。 对于基元,它们本身通过值传递。

暂无
暂无

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

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