Sunday, December 30, 2012

Passing method arguments - by value or by reference. Theory and examples

When Java passes method arguments (parameters) by value and when by reference?
Here we put the major cases and below you will get an working example of it.

Rules:
  • primitive types are passed by value (example in swapPrimitives function);
  • arrays data is passed by reference (example in swapInArray function);
  • reassigning the argument inside the method does not affect the variable in the caller function;
  • all methods called on the arguments are called on the real object (argument variable could be changed);
We will describe the rules with swap function. Some of the methods are wrong and do not swap its arguments. After the code is the output of the program.

Code example:

public class JavaSwappers {
    
    public static void swapPrimitives( int a, int b ) { 
        // NOT working - primitives in java are passed by value
        int c = a;
        a = b;
        b = c;
    }
    
    public static void swapIntererObjects( Integer a, Integer b ){ 
        // NOT working - assigning operation is not passed to the real object
        Integer c = a;
        a = b;
        b = c;
    }
    
    public static void swapInArray( int[] array, int pos1, int pos2 ){
        int tempValue = array[ pos1 ];
        array[ pos1 ] = array[ pos2 ];
        array[ pos2 ] = tempValue;
    }
    
    protected static class IntegerCapsulator{
        public int value;
    }
    
    public static void swapWithCapsulators( 
            IntegerCapsulator a, IntegerCapsulator b ){
        IntegerCapsulator c = new IntegerCapsulator();
        c.value = b.value;
        b.value = a.value;
        a.value = c.value;
    }
    
    protected interface ExternalAssigner {
        public void assign( ExternalAssigner source );
            // change this to source; 
            // source has to be Object from the same type
    }
    
    protected interface GraphicObject extends ExternalAssigner, Cloneable {
    }
    
    protected static class Point implements GraphicObject {
        protected double x;
        protected double y;
        
        public void set(double _x, double _y){ x = _x; y = _y; };
        public double getX(){ return x; }
        public double getY(){ return y; }

        @Override
        public void assign(ExternalAssigner source) {
            if( source.getClass() != Point.class )
                throw new UnsupportedOperationException( 
                   "Source class differs from this class.");
            Point s = (Point) source;
            x = s.x;
            y = s.y;
        }
        
        void swapWith( GraphicObject other ) throws CloneNotSupportedException {
            if( !this.getClass().equals( other.getClass() ) )
                throw new UnsupportedOperationException( 
                  "Swapping objects of different types is not supported");
        
            GraphicObject temp = (GraphicObject)this.clone();
            this.assign( other );
            other.assign( temp );
        }
        
        @Override
        public String toString(){
            return "[" + x + ", " + y + "]";
        }
    }
    
    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        // swapPrimitives
        {
            int pa = 2;
            int pb = 7;
            System.out.println( "before swapPrimitives: pa=" + pa + "; pb=" + pb );
            swapPrimitives( pa, pb );
            System.out.println( "after  swapPrimitives: pa=" + pa + "; pb=" + pb );
        }
        System.out.println();
        
        // swapIntererObjects
        {
            Integer oa = new Integer( 3 );
            Integer ob = new Integer( 8 );
            System.out.println( 
              "before swapIntererObjects: oa=" + oa + "; ob=" + ob );
            swapIntererObjects( oa, ob );
            System.out.println( 
              "after  swapIntererObjects: oa=" + oa + "; ob=" + ob );
        }
        System.out.println();
        
        // swapInArray
        {
            int[] arr = { 10, 20, 30, 40, 50 };
            int pos1=0;
            int pos2=4;
            System.out.println( "before swapInArray: arr[pos1]=" + arr[pos1] + 
                "; arr[pos2]=" + arr[pos2] );
            swapInArray( arr, pos1, pos2 );
            System.out.println( "before swapInArray: arr[pos1]=" + arr[pos1] + 
                "; arr[pos2]=" + arr[pos2] );
        }
        System.out.println();
        
        // swapWithCapsulators
        {
            IntegerCapsulator ca = new IntegerCapsulator();
            IntegerCapsulator cb = new IntegerCapsulator();
            ca.value = 5;
            cb.value = 9;
            System.out.println( "before swapWithCapsulators: ca.value=" + 
               ca.value + "; cb.value=" + cb.value );
            swapWithCapsulators( ca, cb );
            System.out.println( "before swapWithCapsulators: ca.value=" + 
               ca.value + "; cb.value=" + cb.value );
        }
        System.out.println();
        
        // swapWith method
        {
            Point pointA = new Point();
            Point pointB = new Point();
            pointA.set( 1, 1 );
            pointB.set( 3, 3 );
            
            System.out.println( "before swapWith: pointA=" + pointA + 
                "; pointB=" + pointB );
            try {
                pointA.swapWith( pointB );
            } catch ( CloneNotSupportedException ex ) {
                System.out.println( "CloneNotSupportedException" );
            }
            System.out.println( "before swapWith: pointA=" + pointA + 
                "; pointB=" + pointB );
        }
    }
}
 
Program output:
before swapPrimitives: pa=2; pb=7
after  swapPrimitives: pa=2; pb=7

before swapIntererObjects: oa=3; ob=8
after  swapIntererObjects: oa=3; ob=8

before swapInArray: arr[pos1]=10; arr[pos2]=50
before swapInArray: arr[pos1]=50; arr[pos2]=10

before swapWithCapsulators: ca.value=5; cb.value=9
before swapWithCapsulators: ca.value=9; cb.value=5

before swapWith: pointA=[1.0, 1.0]; pointB=[3.0, 3.0]
before swapWith: pointA=[3.0, 3.0]; pointB=[1.0, 1.0]

No comments:

Post a Comment