Showing posts with label tricky code. Show all posts
Showing posts with label tricky code. Show all posts

Monday, March 16, 2009

Mini Java puzzler - Zapped by static

I was modifying some legacy code (defined as code with no automated tests) and found something unexpected when I tried to use it. The original code was rather complicated (possibly because there were no tests), but this simplified version has the same odd behavior:

public class Test {
    static {
        initName();
    }

    static String name = "Sue";
    static Test instance = new Test();

    public static String getName() {
        return name;
    }

    private static void initName() {
        name = "Bond, James Bond";
    }

    public static void main(String[] args) {
        System.out.println("My name is " +
                Test.getName() + ".");
    }
}

So we have a class with one static variable, three static methods and one static initializer. Other than the static initializer, it looks like a pretty simple class that's easy to understand doesn’t it?

In case you’re not familiar with static initializers, let me paraphrase a bit of Sun’s Java Tutorial: "A static initialization block is a normal block of code enclosed in braces, { }, and preceded by the static keyword. They can appear anywhere in the class body, and the Java runtime guarantees they are called in the order in which they appear in the source code." 

That sounds kind of cool, but what’s the point? Why would you use one? Well, a static initializer executes when the class is loaded into memory and it is normally used to do some kind of one-time processing for the class. In this case, the initializer calls the initName() method when the Test class gets loaded into memory and before it’s main method executes.

So, getting back to the puzzle, the question is this: What does the above code do when you run the class?

Here are the possible answers:
   A) It prints “My name is Sue.”
   B) It prints “My name is Bond, James Bond.”
   C) Nothing, because it doesn’t compile.
   D) None of the above.

I recommend taking some time to figure out your own answer before reading any further. You’ll get more out of this is you do. Don’t worry, I’ll don’t mind the wait.

Ready to look at the answers? Good. First things first. Answer C, "Nothing, because it doesn't compile" is not correct. I included it just so I can tell you that I don’t like that kind of answer on a puzzle, or Java certification exam for that matter. Any IDE worth using will tell you if the code will compile or not. While it may have been a useful skill years a go, when our only tools were stone knives and bearskins, we’ve had better tools for so long now that it seems unreasonable to ask a question where “it won’t compile” is the right answer. OK, back to the puzzle.

What about answer B? Well, if you’ve attended one of Josh Bloch’s Java Puzzlers talks (or read my earlier Mini Puzzler), you know the whole point of this is to show you code that looks simple but behaves strangely. So you probably didn’t pick answer B - even though it looks like that’s exactly what should happen. And you would be right in doing so. The code doesn’t print  “My name is Bond, James Bond.”

What about the ever popular “None of the above.” Sorry, not this time. Answer D is not correct either.

By the process of elimination, the correct answer must be A. It prints “My name is Sue.”  and, as it turns out, that is just what does happen. Don't trust me on this, run it yourself - then come back for the explanation.

When I ran the original test code, I didn’t believe the results. It didn’t make any sense so I ran it in the debugger. If you do the same, you can see that the initName() method does get called before the main() method, and that when initName() finishes, the value of “name” is “Bond, James Bond” - just as we expected.

So what’s going on? How does “name” get set to “Sue”? Well, to mis-quote the spirit of Obi-Wan, “Use the source, Luke.”

In looking at the source, you can see that right after the static initializer, we’re declaring and initializing the “name” variable. Which seems odd because the initName() method already set “name” to a value - so it must already exist, right?

Sort of. The compiler sets aside space for the variable and includes code to initialize it but, because “name” is a static variable, its initialization happens when the class is loaded into memory instead of when the class constructor is called. It also appears that, like a static initializer, static variable initialization also happens “in the order in which it appears in the source code.” So after the static initializer is called, the code that initializes “name” to “Sue” executes and overwrites the value we expected to see. Believe it, or not.

So, how do we fix it? Simple. Swap the two lines so the variable is declared and initialized before the static initializer block gets called. Actually, there’s an even better solution for this kind of situation. Since the static initializer is only determining the value for one variable, have the line that declares the variable call a private static method that returns the variable’s initial value. Doing so would’ve prevented this problem in the first place, and ensures that nobody can accidently re-order the lines and start wondering why they’re seeing a line from a Johnny Cash song instead of something Sean Connery ought to be saying.

If you’ve got any feedback on this please post a comment.

Thanks for reading,
Burk

Thursday, February 12, 2009

Mini Java Puzzler

I was working on a project and needed to get a Long value from a String. I know the Long class (like the other wrapper classes for primitives) has static methods that do just the thing , so I started typing in my IDE and trusted that I’d find one that worked. As it turns out there are several methods that do similar conversions. Here’s a list of the candidates:

 Long.decode(String nm)
Long.getLong(String nm)
Long.parseLong(String nm)
Long.valueOf(String nm)


So, given that each of these takes a String and returns a Long, what does the following code return? (Notice that the getLongValue() method returns a primitive long:

    public long getLongValue() {
Long value = Long.getLong("23");
return value.longValue();
}

Here’s the list of possible answers:

 A) 23L
B) 0L (zero)
C) It depends.


Before you continue reading, what do you think the right answer is… OK, that’s enough thinking. Let’s take a look at the possible answers and see what seems likely.

Now it seems reasonable that Long’s getLong() method should return the value of the String as a Long, so answer ‘A’ looks pretty good. Then again, if it were that easy why would I bother posting this. Answer ‘B’ doesn’t seem very reasonable - unless getLong() isn’t really converting the value of the String. So that leaves answer ‘C’ as the primary suspect. If you’re familiar with Josh Bloch’s Java Puzzler talks from JavaOne, you’ll probably go with ‘C’ because it is kind of vague and that makes it a safe bet.


And you’d be right. The correct answer is ‘C’.


It turns out that Long.getLong() doesn’t try to convert the value of the passed in String directly. It looks for a System property with that name, retrieves the value associated with it, and converts that. So what the getLongValue() method returns depends on the value of the System property “23″. So, what if there is no System property “23″? In that case, the method throws a null pointer exception because Long.getLong() will return a null. Ouch!

I found this the hard way. I needed to convert a String and picked a likely method from the list provided by my IDE. I was greatly surprised when my unit test failed, so I looked up the JavaDoc on it and realized my mistake.


There are a few morals to this story:

   Unit tests are your friends.
Use the JavaDoc, and make sure you write some
for people using your code.
Hurrying can cause unexpected delays; but those
can become fodder for a blog post.


Until next time, I leave you with the traditional Java Puzzler farewell,
“Don’t code like my brother.”