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.

Advertisements

3 thoughts on “Work towards the compiler

  1. At work we had a bug related to this issue. Someone (who isn’t me) misunderstood some code they were rewriting, checking equality of a String with an Integer.

    Very good to make people aware of this!

    To me (being of Haskell mind purity) “equals” seems like such a horrible function.

    At the very least it should have been in an interface. First of all because then you could use generics to restrict it’s domain. But also because it does not always make sense to compare two objects and conclude that they are equal.

  2. As you may not want to extend String class it could be a good idea to simply make an helper class to run equality tests if you know which kind of types are frequently used in your app.

    Don’t really like to write Integer.valueOf(oneAsInt).toString()) for each equals i want to use 🙂

    • As you may not want to extend String class

      String cannot be extended, it is final 🙂
      public final class String

      …types are frequently used in your app

      I would agree there, perhaps creating a few helpers for String and other frequently used types is an idea to consider on a large project.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s