我知道这个话题非常好,但是......
我正在为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错误!
答案 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中我们“按值传递引用”,当然除了原语之外。在原语的情况下,它们本身就是通过值传递的。