Friday, March 18, 2011

Passing Variables into Methods- Java Passing Mechanism

Every Programming Language has its own way of passing the variables into methods. There are basically two ways of passing variables- Pass by Reference and Pass By Value. The former deals with the passing of reference or pointer to particular variable and the latter involves passing a copy of the variable to the method. C supports both ways of passing and the Pass By Reference is supported b means of Pointers. Every Java Beginner ponders over “Is Java a Pass By Value?” or “Is it a Pass By reference?” or “Both?”. Before answering the question i would like to throw light on Passing Object Reference variables and Passing primitive reference variables.

Object Reference Variables: These are the variables which refer to the object of the declared type or its subtype. Something like

Animal a = new Animal()

where a is the reference variable

Passing Object Reference Variables:

When a object variable is passed into the method, only the copy of the Object reference is passed and not the Object itself. The bit pattern in the reference variable is copied into the method parameter. What is this bit pattern? This bit pattern is the address of the specific object in the memory (on the heap). In other words, both the caller and the called method will now have identical copies of the reference and thus both will refer to the same exact object on the heap.

Code Example:

import java.awt.Dimension;
class PassObjectRef
{

public static void main(String[] args)
{

Dimension plotDimension = new Dimension(20,30);
PassObjectRef passObj=new PassObjectRef();
System.out.println("B4 Updating: "+
"W: "+plotDimension.width+"H:"+plotDimension.height);
//Before the object values are altered

passObj.updateDimension(plotDimension );
System.out.println("After Updating: "+"W:"+plotDimension.width+" H:"+plotDimension.height);
//After the object values are altered

}
void updateDimension(Dimension dim)
{

dim.height+=10; //Notice the values being changed here.
dim.width+=20;

}
}
Output:

B4 Updating: W: 20 H: 30
After Updating: W: 40 H: 40

Notice that the values being updated in the updateDimension() method are being also reflected outside the scope of the method. That means both the plotDimension and dim object references are referring to the same object on the heap.

Passing Primitive Variables:

When a primitive variable is passed the value with in the variable is copied into the method parameter, which is nothing but the pass-by-copy-of-the-bits-in-the-variable.

Code Snippet:

class PassPrimVar
{

public static void main(String[] args)
{
int primitiveVariable =4;
PassPrimVar passObj =new PassPrimVar();
System.out.println("Before Updating Value: "+primitiveVariable );
// Value being printed before changing

passObj.updateValue(primitiveVariable);
System.ou.println("After Updating Value: "+primitiveVariable );
// Value being printed after changing. Notice there is no difference

}
void updateValue(int var)
{

var+=40; //Value being Changed Here
System.out.println("While Updating Value: "+var);

}
}

Output:

Before Updating Value: 4
While Updating Value: 44
After Updating Value: 4

Notice that the Value is same before and after the updateValue() method has been executed. But in the method the value has been changed. In other words the value being changed in the method is not being reflected in the main() method, its local to the scope of the method in which it is changed.

Does Java Use Pass-By-Value?

Here is the main confusion- Does Java Use Pass By Reference for Object Reference Passing and Pass By Value for Primitive Variable Passing? Java is actually pass-by-value for all variables running within a single VM. Pass By Variable is nothing but passing the variable value. It is same even if you pass and object reference variable or an primitive variable, you are always passing the copy of the bits in the variable. So for passing Object reference variable you are passing the copy of bits which actually is the reference (or address) to the object on the heap and this results in both the reference variables referring to the same object. Because two identical reference variables refer to the exact same object, if the called method modifies the object, the caller will see that the object the caller’s original variable refers to has also been changed. But keep in mind- Suppose in the called method the object reference is reassigned a new object, the caller’s original variable will still refer to the same object on the heap. In this case there will be two references and two objects on the heap. See the code excerpt below:

void do()
{

Animal animal = new Animal(”Dog”);
//New Animal object created on the heap with name Dog referenced by animal
kill(animal); // animal being passed to the kill() method

}
void kill(Animal ani)
{

/*
Method receives a copy of the reference, but animal and ani both still refer to same object
*/

ani =new Animal(”Cat”);

/*
But after this statement, the animal reference still refers to the object by name “Dog”,but the ani reference now refers to the object by name “Cat”.
There are 2 references referring to 2 different objects on the heap.
*/

}

Coming to the passing of primitive variables it is pretty simple and straight forward. When you pass the primitvie variable into a method, you’re passing a copy of the bits representing the value. For example if you pass an int variable with the value 6, and try to change the value in the called method, we can change it but the modifications will not be reflected in the caller’s vairable.

So the bottom line is- Java always uses Pass By Value- Be it for passing Object Reference Variable or primitive variables.


Shadowing Variables:

Shadowing involves redeclaring a variable that’s already been declared somewhere else (In the lines of code before the current line).
The effect of shadowing is to hide the previously declared variable in such a way that it may look as though you’re using the hidden variable, but you’re actually using the shadowing variable. You might find reasons to shadow a variable intentionally, but typically it happens by accident and causes hard-to-find bugs. On the exam, you can expect to see questions where shadowing plays a role.

You can shadow an instance variable by declaring a local variable of the same name, either directly or as part of an argument:
class Ferrari {
static int size = 7;
static void changeIt(int size) {
size = size + 200;
System.out.println("size in changeIt is " + size);
}
public static void main (String [] args) {
Ferrari f = new Ferrari();
System.out.println("size = " + size);
changeIt(size);
System.out.println("size after changeIt is " + size);
}
}

The preceding code appears to change the size instance variable in the changeIt() method, but because changeIt() has a parameter named size, the local size variable is modified while the instance variable size is untouched. Running class Ferrari prints

Output as

size = 7
size in changeIt is 207
size after changeIt is 7

Things become more interesting when the shadowed variable is an object reference, rather than a primitive:
class Car {
int carNum = 28;
}
class Ferrari {
Car myCar = new Car();
void changeIt(Car myCar) {
myCar.carNum = 99;
System.out.println("myCar.carNum in changeIt is " + myCar.carNum);
myCar = new Car();
myCar.carNum = 420;
System.out.println("myCar.carNum in changeIt is now " + myCar.carNum);
}
public static void main (String [] args) {
Ferrari f = new Ferrari();
System.out.println("f.myCar.carNum is " + f.myCar.carNum);
f.changeIt(f.myCar);
System.out.println("f.myCar.carNum after changeIt is "
+ f.myCar.carNum);
}
}

The preceding code prints out this:
f.myCar.carNum is 28
myCar.carNum in changeIt is 99
myCar.carNum in changeIt is now 420
f.myCar.carNum after changeIt is 99

You can see that the shadowing variable (the local parameter myCar in changeIt()) can still affect the myCar instance variable, because the myCar parameter receives a reference to the same Car object. But when the local myCar is reassigned a new Car object, which we then alter by changing its carNum value, Ferrari’s original myCar instance variable is untouched.


Important Notes:


1. The Java programming language doesn't let you pass methods into methods. But you can pass an object into a method and then invoke the object's methods.
2. Everything in Java is passed by value. Objects, however, are never passed at all.
3. The values of variables are always primitives or references, never objects.


Thanks to Reference of Mohamed Sanaulla ..


No comments:

Post a Comment