Reputation: 983
I know this subject is very beaten, but ...
I'm programming an app for android in java, but I come from c++ , where the question of value or reference is very explicit. The problem is:
Initially I have a class called Item that has a variable public int ID.
In a class called ListingItem, I have a static List list with two item added to it, each has assigned to its variable ID the value 1. In this class there is also a function public static List getList() that returns List, specifically, the List list of this class.
In another class, called Fragment, I have a List ItemList and a function private List getList() that returns List.
The getList() of Fragment class does the following:
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;
}
Another function of class Fragment use Fragment.getList() like this:
private functionOfFragment()
{
List<Item> ItemList = getList();
itemList.get(0).ID = 2;
itemList.get(1).ID = 2; // changing from 1 to 2
}
However, the value of ListingItem.list.get(0).ID and ListingItem.list.get(0).ID are also the value 2. How is this possible?
obs: THIS CODE IS ONLY REPRESENTATIVE, THE PROBLEM ISN'T THE SYNTAX ERROS!
Upvotes: 1
Views: 106
Reputation: 1419
I would say in Java we "pass references by value", except primitives of course. In case of primitives they are itself passed by value.
Upvotes: 1
Reputation: 37845
Parameter passing by value in Java is not the same as in C++.
In Java:
Therefore an object reference in Java is functionally like a pointer, but you cannot dereference and reassign it.
In C++ you can do this:
#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;
}
You cannot do that in Java. A Java reference variable is not a C++ pointer, not a C++ reference and not a C++ object value.
You can only do this:
void reassignLocal(SomeObj* obj) {
obj = new SomeObj(5);
}
And this:
void mutateElsewhere(SomeObj* obj) {
obj->num = 5;
}
So creating a new List like the following:
static List<SomeObj> shallowCopy(List<SomeObj> input) {
List<SomeObj> output = new ArrayList<SomeObj>(input.size());
for (SomeObj obj : input)
output.add(obj);
return output;
}
Only copies the references from one list to the other. They are the same objects. Mutating output
elements will mutate input
elements and vice-versa. To change this you need to actually instantiate new objects.
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;
}
Upvotes: 2
Reputation: 30310
In Java, pass by value vs. reference is very explicit too. There is only pass-by-value--for everything.
In your example, you retrieve Item
instances from the ArrayList
, and copies of the references are passed to returnList.add
. Still, the copies point to the same objects in memory as the originals, and they all can be "dereferenced" with the dot operator.
That's what you are doing when you say itemList.get(1).ID = 2
. Because ID
is public, when you dereference, you are accessing the object and setting its value to something new.
So references to objects (and primitives too) are passed by value, but the objects they reference can be altered in the manner defined by the class API. That is not the same as pass-by-reference, which is not feasible in a language that manages memory.
Upvotes: 3
Reputation: 201447
Because the variables refer to the same referent. The value of every java.lang.Object
(e.g. objects not primitives) variable is the reference address (e.g. the "confusing" default toString()
implementation), I hope that helps! Also, this is backwards returnList return;
.
Upvotes: 2