问题
Consider following case.
List<Integer> listOne = new ArrayList<>();
List<Integer> listTwo = new ArrayList<>();
listOne.add(1);I think this happens due to
listOne.add(2);
listOne.add(3);
Collections.reverse(listOne);
listTwo = listOne; //listTwo has same reference
Collections.reverse(listOne);
System.out.println(listOne); //out put [1, 2, 3]
System.out.println(listTwo); // same out put
Java is pass by value, where values (for non primitive types) happen to be references.
I think this provide survival for java for this kind of scenario. To be honest why java
try to avoid pass by reference
and try to be different from some of other languages
? while java still suffering from pass by reference behaviors?
Edit: additionally please some one explain what happen in above code
回答1:
Java does not suffer from pass by reference behaviors, it enjois them :)
when you write
List listOne = new ArrayList<>();
you have three things to consider:
1) a variable, which is a chunk of memory, and is named listOne
2) an object on the heap, with is an instance of ArrayList, which is a larger chunk of memory, and has no name
3) value of the listOne variable, which is not a memory chunk, but is a set of 0s and 1s placed in the memory of the variable listOne, and that value also has no name.
Now when we talk if listOne is passed by value or by reference, we use imprecise jargon which leads to misunderstanding. listOne (thing 1) is not passed at all, neither by value nor by reference. The value of listOne (thing 3) is passed, and this gives access to the ArrayList object (thing 2). So if we use name "listOne" but mean thing 3, it is passed by value, and if we mean thing 2, it is passed by reference. In both cases, name "listOne" is not correct name for thing 2 or thing 3, but it is used because it is short and convenient.
回答2:
Java is pass by value.A copy of actual argument is passed to parameters.It is evident in case of primitive data types where changes in formal parameters is not shown in actual arguments.
static void incre(int a)
{
a++;
}
public static void main (String a[])
{
int c=3;
incre(c);
System.out.println(c); //still prints 3
}
Exact thing happens in case of references, but making a copy of reference does not create a new object, they both point to same object now.Hence changes made by references is reflected here.
class Demo {
int c =2;
Demo(int c)
{
this.c=c;
}
void incObject (Demo x)
{
(x.c)++;
}
int show()
{
return c;
}
public static void main (String []args)
{
Demo o = new Demo(1);
o.incObject(o);
System.out.print(o.show()); //prints 2
}
}
回答3:
Collections.reverse();
modifies the backing array. This is clear from the implementation:
public static void reverse(List<?> list) {
int size = list.size();
if (size < REVERSE_THRESHOLD || list instanceof RandomAccess) {
for (int i=0, mid=size>>1, j=size-1; i<mid; i++, j--)
swap(list, i, j);
} else {
ListIterator fwd = list.listIterator();
ListIterator rev = list.listIterator(size);
for (int i=0, mid=list.size()>>1; i<mid; i++) {
Object tmp = fwd.next();
fwd.set(rev.previous());
rev.set(tmp);
}
}
}
Now, listOne
and listTwo
have the same reference which points to the same backing array. So, no matter which handle(listOne or listTwo) modifies the backing array, the other will reflect the same changes. In your case:
Collections.reverse(listOne); // backing array has [3,2,1]
listTwo = listOne; //listTwo has same reference
Collections.reverse(listOne); // backing array has [1,2,3]
System.out.println(listOne); //out put [1, 2, 3]
System.out.println(listTwo); // same out put
As far as pass by value/reference is concerned. You said it yourself:
Java is pass by value, where values happen to be references.
why java try to avoid pass by reference and try to be different from some of other languages?
One of the main reasons would be that Java(JVM) manages its own memory.
回答4:
Collections.reverse(listOne);
passes the reference to listOne
(the object) by value, which is how one defines "pass by reference". Everything other than primitives is passed this way: by reference. It does not try to avoid it, it is only different from C++ in that it doesn't explicitly use pointers.
EDIT: Okay, I think I see where you're coming from.
private static void changelist(List<Integer> list) {
list.add(4);//This modifies the list object
list = new ArrayList<Integer>();//This modifies the local copy of the reference to the list object
list.add(5);
}
public static void main(String[] args) {
List<Integer> list = new ArrayList<Integer>();
list.add(1);
list.add(2);
list.add(3);
System.out.println(list);//output is [1,2,3]
//This copies the value of the reference.
//If you modify the object in the underlying
//function, changes will be preserved when you return
//However if you modify what the reference points to,
//the function will only modify the local copy
changelist(list);
System.out.println(list);//output is [1,2,3,4]
}
来源:https://stackoverflow.com/questions/18249555/is-java-pass-by-value-or-pass-by-reference-or-both