WTF? Or just anti-pattern?
WTF? Or just anti-pattern?

In the end of last year I came across the some code similar to the following:

    1: public class SingleValue<T extends Object> {
    2:   T object;
    4:   public SingleValue (T value) {
    5:     object = value;
    6:   }
    8:   public boolean equals (SingleValue<T> other) {
    9:     if (other == null) {
   10:       return false;
   11:     }
   12:     if (other == this) {
   13:       return this;
   14:     }
   15:     if (obj.getClass () != getCLass ()) {
   16:       return false;
   17:     }
   18:     SingleValue<T> otherSingleValue = (SingleValue<T>) other;
   19:     return new EqualsBuilder()
   20:       .appendSuper(super.equals(obj))
   21:       .append(object, otherSingleValue.object)
   22:       .isEquals();
   23:   }
   24: }

Some, if not most, of you will recognize this from apache commons EqualsBuilder.

When searching for reverences to this SingleValue class and all one would find were instances of the type SingleValue<String> and, upon asking the team that was maintaning that code, it was clear that no other generic type would ever be used.

In effect this class can be deleted and the instances of this class can then be changed, without any loss of reliability, to a simple instance of type String.

If before one would have something like:

    1: SingleValue<String> stringValue =
    2:   new SingleValue<String> ("Hello garbage collector!");
    4: if (stringValue.equals("All is fine, nothing to see.")) {
    5:   System.out.println("It's all fine.");
    6: } else {
    7:   System.out.println("Upsy daisy!");
    8: }

would become a much simpler:

    1: String stringValue = "Hello garbage collector!";
    3: if (stringValue.equals("All is fine, nothing to see."))
    4:   System.out.println("It's all fine.");
    5: } else {
    6:   System.out.println("Upsy daisy!");
    7: }

The more complex solution of using the SingleValue<String> has some "low-level" drawbacks:

  • creating unnecessary objects. If you compare two SingleValue<String> you will in fact be creating the String objects and the encapsulating them in SingleValue objects. So twice as many objects created for everyString that is necessary.
  • when using the equals method a EqualsBuilder instance is created and two of it's methods are called. The first, appendSuper(boolean), is a rather light and probably will be inlined. The second one on the other hand is not so light. The append(Object, Object) will do several checks before eventually reaching the String.equals(String) that is to be used.

Which would you prefer to maintain?