Thursday 8 April 2010

Java Experiments

Hi all,

So I've been frantically packing and moving over the last week which means once more I have a pithy excuse to have posted as regularly as I promised, my bad!

Again this is a Java posting, so a warning to those adverse to seeing source code!

I ran across another common misunderstanding with Java for those first developing with it (and indeed for some more experienced developers!).  This was also highlighted in a recent TheDailyWTF article.  The mis-understanding is explained in the code below and is often asked about as an interview or certification question.

Thanks to Scott Selikoff, (I co-opted his code example).

package org.martijnverburg.experiments;

/**
 * This class runs experiments to prove various pass by value 
 * and pass by reference rules in the JDK
 *
 * The use of System.out.println is generally frowned 
 * upon, but I'll forgive myself in this case.
 * 
 * This probably should be a nice Unit test, many 
 * apologies!
 *
 * @author Martijn Verburg (aka karianna)
 */
public class PassByValuePassByReferenceExperiments
{

  /**
   * Fire off the experiments
   *
   * @param args - Not used
   */
  public static void main(String[] args)
  {
    PassByValuePassByReferenceExperiments test = new PassByValuePassByReferenceExperiments();
    test.changeValueOfObjectPassedIn();
  }

  /**
   * This method challenges a false assumption whereby the 
   * developer may think that when they pass an object reference 
   * into a method as an argument, then change the value of 
   * that object in the method, that the reference they hold 
   * onto in the calling method retains that changed value.
   *
   * TODO:  The explanation above isn't the clearest English, 
   * try to tidy that up later.
   *
   * If you misunderstand how this works in Java you may expect
   * to see the result as:

   * 
   * 10
   * 10
   *
   * The actual output of this experiment is:
   * 
   * 10
   * 3
   */
   private void changeValueOfObjectPassedIn()
   {
     Integer x = new Integer(3);
     changeX(x);
     System.out.println("Value of x is = [" + x + "]);
   }

  /**
   * The key concept here is the the Integer x declared 
   * in the argument list for the method is a local copy 
   * of the original reference.  So when you alter its value, 
   * you're only altering the local version, which incidentally 
   * falls out of scope when the method ends.
   */
   private void changeX(Integer x)
   {
     x = new Integer(10);
     System.out.println("Value of x is = [" + x + "]);
   }

}

So are we there yet?  Sadly no, all to often developers forget the fundamental rules like this and for new developers this concept can be especially confusing.


But although some developers might look down upon those who don't have the fundamentals memorised, I actually feel that it can be OK to be a bit forgetful or hazy, after all you can't remember it all!  I say that with the proviso that you should actively engage in improving your fundamentals knowledge, writing tiny test cases/experiments like the above code can be a very helpful aid.

No comments:

Post a Comment