Work towards the compiler

This is the first post !

You may think that you know what you are doing because it is your code after all, but if a mistake can be done it will be done (when refactoring or by someone else modifying your code).

This post illustrates how easy it is to write error prone code, but also how little effort it may take to reduce the danger.

Equals method:

Consider the following code sample:

package javarizon;

import java.util.ArrayList;
import java.util.List;

public class TypeSafeEquals {
 public static void main(String[] args) {
 final String one = "1";
 final int oneAsInt = 1;
 final Object object = "1";

 // Compiles...
 one.equals(oneAsInt);

 // First idea: It works, but if you pass an object by mistake it still
 // compiles. Have fun debugging !
 one.equals(String.valueOf(oneAsInt));
 one.equals(String.valueOf(object));

 // Better idea: It works, but will not compile if you use an object.
 one.equals(Integer.valueOf(oneAsInt).toString());
 one.equals(Integer.valueOf(object).toString());

 // Even better: it only takes an int.
 one.equals(Integer.toString(oneAsInt));
}
}

The first version is often used because it easy to come up with, but if you accidentally use a bad parameter, it will compile and not even break at runtime: it results in a bug that will be difficult to spot.

It might even work by chance in some cases (there are only two possible return values) depending on your application logic and data. Imagine you use such non-type safe code everywhere in your code, you or someone using your code is doomed to make a mistake at some point.

In the second version, the chances of committing a mistake were drastically reduced simply by using code that will accept less types, it does not compile when passed an object:

The method valueOf(String) in the type Integer is not applicable for the arguments (Object)

Consider using code completion on a method to quickly check what types it can take, if there are too many (especially evil Object) try looking for a more restrictive alternative. You could also write a static method that takes two Strings and uses equals internally, the only problem is that you have to do this for every possible type.

Conclusion:

Being careful is not enough, when properly helped the compiler is much more careful than you ever will. Always strive to maximize type-safety when writing code. Ensure the compiler is on your side by adapting your programming style to it.

I will try coming up with more examples in the future posts.