First a definition so everything is clear.
Pass by value - The actual value of a parameter is copied into a "new" memory address and any manipulation of this value will not cause the original value to change. Every call to the method will create a new parameter with a new value which is uniquely changed in the method.
Pass by reference - The parameter is just an alias for the actual value. every time the alias is used the real value is actually used. Thus a change to the value in the method will change the value of the object if it is called from outside the method as well.
Java is pass by value. See the formal explanation here.
Why the confusion then?
Well because even though in a formal sense Java is pass by value there are some instances where the result seem to contradict this. For all you zealots out there, I know the differenceon pass by value/reference and the below example is merely to show why some people have a hard time to grasp this. In a formal sense this is pass by value even though the result is "odd".
First a small pojo.
******************************
public class A
{
private String name;
private int age;
/**
* @return the name
*/
public String getName()
{
return name;
}
/**
* @param name the name to set
*/
public void setName(String name)
{
this.name = name;
}
/**
* @return the age
*/
public int getAge()
{
return age;
}
/**
* @param age the age to set
*/
public void setAge(int age)
{
this.age = age;
}
}
*********************************
The a class using this pojo.
**********************************
public class Runner
{
/**
* @param args
*/
public static void main(String[] args)
{
Runner r = new Runner();
r.init();
}
private void init(){
A a = new A();
a.setName("King");
a.setAge(25);
System.out.println("A name before method call" + a.getName());
System.out.println("A age before method call" + a.getAge());
this.changeValue(a);
System.out.println("A name after method call" + a.getName());
System.out.println("A age after method call" + a.getAge());
}
private void changeValue(final A a){
a.setName("Kong");
a.setAge(35);
System.out.println("A name in method: " + a.getName());
System.out.println("A age in method: " + a.getAge());
}
}
*********************************************
The output on the screen is
A name before method callKing
A age before method call25
A name in method: Kong
A age in method: 35
A name after method callKong
A age after method call35
*************************************************
Now from my point of view this looks like some kind of reference. And here is the rather dubious part of this,
Object references are passed by value.
Read that again. It is fundamental. It is actually the "pointer" towards the memory address which is copied and sent to the method as a formal parameter. this means that all changes inside the object is actully propagated outside of the method.
OK but what about this?
private void changeValueComplex(final A a){
A b = a;
b.setName("Jonas");
b.setAge(35);
System.out.println("B name in method: " + b.getName());
System.out.println("A name in method: " + a.getName());
System.out.println("B age in method: " + b.getAge());
System.out.println("A age in method: " + a.getAge());
}
********************
Sorry mate, no use. Same result. Hrm what to do. Wait, I got it!
Add this to A:
implements Cloneable
and this method
public Object clone() throws CloneNotSupportedException {
return (A) super.clone();
}
private void changeValueByClone(final A a){
try {
A b = (A)a.clone();
b.setName("Jonas");
b.setAge(35);
System.out.println("B name in method: " + b.getName());
System.out.println("A name in method: " + a.getName());
System.out.println("B age in method: " + b.getAge());
System.out.println("A age in method: " + a.getAge());
}catch (Exception e){
e.printStackTrace();
}
}
Now we actually could manipulate the values in one object without affecting the other one.
0 comments:
Post a Comment