Anti-pattern:
An anti-pattern (or antipattern) is a common response to a recurring problem 
that is usually ineffective and risks being highly counterproductive. The term, 
coined in 1995 by Andrew Koenig, was inspired by a book, Design Patterns, in 
which the authors highlighted a number of design patterns in software 
development that they considered to be highly reliable and effective.
— source http://en.wikipedia.org/wiki/Anti-pattern


Here at Schuberg we spend quite some time going through bugs reports from 
automated scanners, you have probably seen the mails coming by on the ML. As 
part of our work we have encountered a number of problems that keep on popping 
up in the code base. So here is my first attempt to clarify why a certain 
pattern is wrong and hopefully help developers to avoid this.

So first up is the equality operator, ==.  This operator is commonly used in 
many languages to compare if two items are equal. The trick with this operator 
in java is to know exactly what you are comparing, because it matters.

Consider this piece of code:

public class App
{
    public static void main(String[] args)
    {
        int a = 1;
        int b = 1;

        if (a == b) {
            System.out.println("Equal!");
        } else {
            System.out.println("Different!");
        }
    }
}

The expected outcome is “Equal!” and indeed it prints just that. Now consider 
the following code:

public class App
{
    public static void main(String[] args)
    {
        Integer a = new Integer(1);
        Integer b = new Integer(1);

        if (a == b) {
            System.out.println("Equal!");
        } else {
            System.out.println("Different!");
        }
    }
}

The result of running this bit of code is “Different!”. With == you are telling 
the java compiler to compare the two variables. The variable are references to 
Objects, so it will do exactly what you tell it to do, compare the two object 
references. As you give it two different objects, the result willl be 
“Different!”. The correct way of comparing the contents of two objects is to 
use the equals method. Consider the following piece of code:

public class App
{
    public static void main(String[] args)
    {
        Integer a = new Integer(1);
        Integer b = new Integer(1);

        if (a.equals(b)) {
            System.out.println("Equal!");
        } else {
            System.out.println("Different!");
        }
    }
}


This will again be “Equals!”.

Why is this often a problem? There are a lot or reasons why these bugs came to 
exist in CloudStack (or any other project). For example somebody might cause 
this bug by changing the return type of a function from long to Long. The first 
one is a primitive which can be compared with == and the second one is an 
Object which might result in another comparison than you intended. Findbugs 
will catch these types of comparisons and warn you for them. See commit 
d1efdca50622a0b67ae1a286aad3297b1c748e9e for an example.



Oh and what does this print?

public class App
{
    public static void main(String[] args)
    {
        Integer a = 1;
        Integer b = 1;

        if (a.equals(b)) {
            System.out.println("Equal!");
        } else {
            System.out.println("Different!");
        }
    }
}


Surprise!, it prints “Equals!”.  This is a boxed integer and java keeps a pool 
of these so internally the object is cached and both a and b get the same 
objects assigned to them by the internal boxing logic. Just never rely on this! 
It only works in specific cases and is implementation specific per JVM vendor 
and JVM version. 

Cheers,

Hugo


P.S. If you have another anti pattern feel free to post em in this thread.

Reply via email to