*** MOVED ***

NOTE: I have merged the contents of this blog with my web-site. I will not be updating this blog any more.

2007-01-21

"Concepts, Techniques, and Models of Computer Programming"

I just finished reading "Concepts, Techniques, and Models of Computer Programming" by Peter Van Roy and Seif Haridi. If you are the kind of person who thinks that "The Art of Computer Programming" and "Structure and Interpretation of Computer Programs" are good books, then you owe it to yourself to check this book out.

There is a slightly-dated version of the book available online (PDF, 3.4 MB), if you want to preview some of the content before buying it. There is also an Indian edition of the book published by Prentice Hall of India (ISBN: 81-203-2685-7) and priced at Rs 450. The book's web site links to some reviews and you can also read my review of the book.

2007-01-20

Local Variables in Java

The other day I was reviewing some Java code written by a colleague. I noticed that he was in the habit of declaring all the variables used by a method at the beginning of the method body rather than in the places where they were first used. I pointed out that declaring a variable only when it is first required makes the code more readable.

While he agreed to change the style of his code, he was still reluctant to move the declaration of a variable used only within a loop from outside it to inside it. For example, he was reluctant to change:

String s;
for( int i = 0; i < 10; i++)
{
s = String.valueOf( i);
}

to:

for( int i = 0; i < 10; i++)
{
String s = String.valueOf( i);
}

He believed that only one variable is created in the former case while 10 variables are created in the latter - clearly it is more efficient to declare a single variable outside the loop and keep reusing it inside the loop!

I then pointed out the section in the JVM specification that says that a JVM uses a fixed-size array for storing the values of local variables used in a method and each local variable maps to an index in this array. A Java compiler calculates the size of this array during the compilation of a method and declares it in the generated bytecode for the method.

Since he was still sceptical, I compiled both the variants to bytecode, used javap -c to produce the dissassembled code and used diff to show that the generated code was the same in both the cases (except for the indices used for s and i). I then used a simple modification of using the JVM Emulator Applet written by Bill Venners as a standalone application to show the bytecode variants in execution and demonstrate that the size of the local variables array really remains constant throughout.

He was finally convinced.

On the other extreme, I have another colleague who is in the masochistic habit of introducing new scopes to isolate the local variables used only in a section of a method's body. That is, something like:

{
Foo x = wombat.snafu( );
// Use x here.
...
}
{
Bar y = new Bar( a, b, c);
// Use y here.
...
}

2007-01-11

Generics in Java and Return Types

Consider a class C that implements an interface I.

While the following is allowed:

I foo( )
{
return new C( );
}

the following is not:

ArrayList<I> foo( )
{
return new ArrayList<C>( );
}

In the first case, callers expect to get an object implementing the interface I and therefore it is correct for foo( ) to return an object of class C. In the second case, callers expect to get an ArrayList containing objects implementing the interface I and therefore it should again be correct for foo( ) to return an ArrayList containing objects of class C, right?

Consider what happens if the compiler were to allow such code to compile. Callers can then add objects of another class X, which also implements the interface I, to the returned ArrayList with the result that the original ArrayList, which is only supposed to contain objects of class C, now also contains objects of an incompatible class X!

A better way to define the second case is:

ArrayList<? extends I> foo( )
{
return new ArrayList<C>( );
}

(You can also return an ArrayList<I> instead, but that loosens up the definition of the returned object.)

Thanks to Steve for clearing up my muddied thinking.