[英]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).ID和ListingItem.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.