Subscribe to cfoley's Blog        RSS Feed
-----

Quirky Hello World!

Icon Leave Comment
I came across something quite interesting while I was coding today. Before I explain further, take a look at the following short Java program. It outputs two lines of text. Each line could be one of the following:

No Message
Hello World!
Not today.

Write down what you think each line will be, then scroll down for the answer. Don't cheat now! Write down what you think the output will be first. :P

package jUnitOddity;

public class QuirkyHelloWorld {
	
	private  String message = "No message";
	
	public static void main(String [] args) {
		QuirkyHelloWorld a = new QuirkyHelloWorld();
		a.implementationA();
		QuirkyHelloWorld b = new QuirkyHelloWorld();
		b.implementationB();
	}
	
	public void implementationA() {
		display(message, prepare());
	}
	
	public void implementationB() {
		boolean reallyDisplay = prepare();
		display(message, reallyDisplay);
	}
	
	private boolean prepare() {
		message = "Hello World!";
		return true;
	}
	
	private void display(String greeting, boolean reallyDisplay) {
		if (reallyDisplay) {
			System.out.println(greeting);
		} else {
			System.out.println("Not today.");
		}
	}
	
}



The output is:
Spoiler


Before I explain, take a look at this modified version. It's the same program but this time I'm using a String Buffer instead of a String. Again, write down what you think the two lines are going to be.

(Hint: it's different from last time)

package jUnitOddity;

public class StringBufferHelloWorld {
	
	private StringBuffer message = new StringBuffer("No message");
	
	public static void main(String [] args) {
		StringBufferHelloWorld a = new StringBufferHelloWorld();
		a.implementationA();
		StringBufferHelloWorld b = new StringBufferHelloWorld();
		b.implementationB();
	}
	
	public void implementationA() {
		display(message, prepare());
	}
	
	public void implementationB() {
		boolean reallyDisplay = prepare();
		display(message, reallyDisplay);
	}
	
	private boolean prepare() {
		message.replace(0, 12, "Hello World!");
		return true;
	}
	
	private void display(StringBuffer greeting, boolean reallyDisplay) {
		if (reallyDisplay) {
			System.out.println(greeting);
		} else {
			System.out.println("Not today.");
		}
	}
	
}



This time we get:
Spoiler


If you think the output to the first one was crazy, surely it's even crazier that these two programs give different outputs. Let's have a look at what's going on.

ImplementationB is more consistent so let's start with that. Prepare() is called, changing the message and returning true. These are passed to display(). Because the boolean is always true, we never display "Not today." so we get "Hello World" as intended.

What changes in implementationA? The key to this is remembering that an object variable is only a reference to an object, not the object itself. This time, the message is passed before prepare() is called. In the StringBuffer example, prepare() modifies the StringBuffer so message and greeting are referring to the same StringBuffer object. However, strings are immutable. In that example, we're creating a new String object ("Hello World!") and getting message to point to it. But by that time it's too late. Greeting is already pointing to "No message" and doesn't care about message or whatever object it's referencing.

The moral of this story is to always be clear of the difference between an object and a variable, and remember when calling methods that you pass the object, not the variable.

I hope you found this interesting. If you got the answers right be sure leave a comment exercising your bragging rights.

0 Comments On This Entry

 

July 2014

S M T W T F S
  12345
6789101112
13141516171819
20212223242526
27282930 31   

Tags

    Recent Entries

    Recent Comments

    Search My Blog

    0 user(s) viewing

    0 Guests
    0 member(s)
    0 anonymous member(s)