They're two completely different things. == compares the object reference, if any, contained by a variable. .equals() checks to see if two objects are equal according to their contract for what equality means. It's entirely possible for two distinct object instances to be "equal" according to their contract. And then there's the minor detail that since equals is a method, if you try to invoke it on a null reference, you'll get a NullPointerException.

For instance:

class Foo {
    private int data;

    Foo(int d) {
        this.data = d;
    }

    @Override
    public boolean equals(Object other) {
        if (other == null || other.getClass() != this.getClass()) {
           return false;
        }
        return ((Foo)other).data == this.data;
    }

    /* In a real class, you'd override `hashCode` here as well */
}

Foo f1 = new Foo(5);
Foo f2 = new Foo(5);
System.out.println(f1 == f2);
// outputs false, they're distinct object instances

System.out.println(f1.equals(f2));
// outputs true, they're "equal" according to their definition

Foo f3 = null;
System.out.println(f3 == null);
// outputs true, `f3` doesn't have any object reference assigned to it

System.out.println(f3.equals(null));
// Throws a NullPointerException, you can't dereference `f3`, it doesn't refer to anything

System.out.println(f1.equals(f3));
// Outputs false, since `f1` is a valid instance but `f3` is null,
// so one of the first checks inside the `Foo#equals` method will
// disallow the equality because it sees that `other` == null
Answer from T.J. Crowder on Stack Overflow
Top answer
1 of 16
213

They're two completely different things. == compares the object reference, if any, contained by a variable. .equals() checks to see if two objects are equal according to their contract for what equality means. It's entirely possible for two distinct object instances to be "equal" according to their contract. And then there's the minor detail that since equals is a method, if you try to invoke it on a null reference, you'll get a NullPointerException.

For instance:

class Foo {
    private int data;

    Foo(int d) {
        this.data = d;
    }

    @Override
    public boolean equals(Object other) {
        if (other == null || other.getClass() != this.getClass()) {
           return false;
        }
        return ((Foo)other).data == this.data;
    }

    /* In a real class, you'd override `hashCode` here as well */
}

Foo f1 = new Foo(5);
Foo f2 = new Foo(5);
System.out.println(f1 == f2);
// outputs false, they're distinct object instances

System.out.println(f1.equals(f2));
// outputs true, they're "equal" according to their definition

Foo f3 = null;
System.out.println(f3 == null);
// outputs true, `f3` doesn't have any object reference assigned to it

System.out.println(f3.equals(null));
// Throws a NullPointerException, you can't dereference `f3`, it doesn't refer to anything

System.out.println(f1.equals(f3));
// Outputs false, since `f1` is a valid instance but `f3` is null,
// so one of the first checks inside the `Foo#equals` method will
// disallow the equality because it sees that `other` == null
2 of 16
52

In addition to the accepted answer (https://stackoverflow.com/a/4501084/6276704):

Since Java 1.7, if you want to compare two Objects which might be null, I recommend this function:

Objects.equals(onePossibleNull, twoPossibleNull)

java.util.Objects

This class consists of static utility methods for operating on objects. These utilities include null-safe or null-tolerant methods for computing the hash code of an object, returning a string for an object, and comparing two objects.

Since: 1.7

Top answer
1 of 2
4

It is unnecessary because instanceof has a built in null check. But instanceof is a lot more than a simple foo == null. It is a full instruction preparing a class check doing unnecessary work before the null check is done. (see for more details http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-6.html#jvms-6.5.instanceof)

So a separate null check could be a performance improvement. Did a quick measurement and no surprise foo==null is faster than a nullcheck with instanceof.

But usually you do not have a ton of nulls in an equals() leaving you with a duplicate unnecessary nullcheck most of the times... which will likely eat up any improvement made during null comparisons.

My conclusion: It is unnecessary.

Code used for testing for completeness (remember to use -Djava.compiler=NONE else you will only measure the power of java):

public class InstanceOfTest {
    public static void main(String[] args) {
        Object nullObject = null;

        long start = System.nanoTime();         
        for(int i = Integer.MAX_VALUE; i > 0; i--) {
            if (nullObject instanceof InstanceOfTest) {}
        }
        long timeused = System.nanoTime() - start;  

        long start2 = System.nanoTime();
        for(int i = Integer.MAX_VALUE; i > 0; i--) {
            if (nullObject == null) {}
        }
        long timeused2 = System.nanoTime() - start2;

        System.out.println("instanceof");
        System.out.println(timeused);       
        System.out.println("nullcheck");
        System.out.println(timeused2);
    }
}
2 of 2
2

Indeed, it is unnecessary and it is the mistake of the authors of the Eclipse template. And it is not the first one; I found more of smaller errors there. For example, the generation of the toString() method when I want to omit null values:

public class A {
    private Integer a;
    private Integer b;

    @Override
    public String toString() {
        StringBuilder builder = new StringBuilder();
        builder.append("A [");
        if (a != null)
            builder.append("a=").append(a).append(", ");
        if (b != null)
            builder.append("b=").append(b);
        builder.append("]");
        return builder.toString();
    }
}

If a is not null and b is, there will be an extra comma before the closing ].

So, regarding your statement: "Now, I guess that the folks writing the code templates for Eclipse JDT are worth their salt, too.", I assume they are, but it would not hurt them to pay more attention to these tiny inconsistencies. :)

๐ŸŒ
EqualsVerifier
jqno.nl โ€บ equalsverifier โ€บ manual โ€บ null
Dealing with null - EqualsVerifier
2 weeks ago - However, you might not want to add a null check, for example because your class is immutable and you check for null in the constructor. There are several things you can do. You can mark your fields with a @Nonnull annotation. EqualsVerifier recognizes annotations named @Nonnull, @NonNull and @NotNull. This should cover the annotations from all the popular annotations providers, like FindBugs and Eclipse.
Top answer
1 of 6
4

Perhaps you are having an old eclipse version. My eclipse generates this:

if (this == obj)
    return true;
if (obj == null)
    return false;
if (getClass() != obj.getClass())
    return false;
2 of 6
2

You are right, if Eclipse does it that way. But it doesn't. On my machine, Eclipse Indigo / Ubuntu, given this Class:

public class Foo {
    private String bar;
}

Eclipse would generate the following equals() method:

@Override
public boolean equals(Object obj) {
    if (this == obj) return true;
    if (obj == null) return false;
    if (getClass() != obj.getClass()) return false;
    Foo other = (Foo) obj;
    if (bar == null) {
        if (other.bar != null) return false;
    } else if (!bar.equals(other.bar)) return false;
    return true;
}

For comparison, here's the equals() method I would write for the same class (using Guava):

@Override
public boolean equals(final Object obj) {
    return obj instanceof Foo ? Objects.equal(bar, ((Foo) obj).bar) : false;
    //          ^--- implicit null check here
}

I use this Eclipse code template to achieve this:

${:import(com.google.common.base.Objects)}
@Override
public boolean equals(final Object obj){
    return obj instanceof ${enclosing_type} ? Objects.equal(${field1:field}, ((${enclosing_type}) obj).${field1}) : false;
}

@Override
public int hashCode(){
    return Objects.hashCode(${field1});
}

@Override
public String toString(){
    return MoreObjects.toStringHelper(this).add("${field1}", ${field1}).toString();
}

Unfortunately, I have to keep one of these around for each cardinality of fields, so I have templates named eq1 (the above), eq2, eq3, eq4 etc. It's a small nuissance, but it's still a lot better than the monster methods generated by Eclipse. Guava docs

๐ŸŒ
Medium
medium.com โ€บ @AlexanderObregon โ€บ javas-objects-equals-method-explained-3a84c963edfa
Javaโ€™s Objects.equals() Method Explained | Medium
1 week ago - Explore Java's Objects.equals() method, a null-safe solution for object comparison. Learn how it prevents NullPointerException and simplifies your code.
Find elsewhere
๐ŸŒ
JoeHx Blog
joehxblog.com โ€บ does-null-equal-null-in-java
Does Null Equal Null in Java? โ€“ JoeHx Blog
October 31, 2018 - I can only use the simple equality operator (the double-equals โ€œ==โ€) or some helper methods, such as Objects.equals(Object, Object). Which is what I did. Below is the short but beautiful Java program I wrote: import java.util.Objects; public class Main { public static void main(final String[] args) { System.out.println("true: " + true); System.out.println("false: " + false); System.out.println(); final String string = null; final Number number = null; System.out.println("null == null: " + (null == null)); System.out.println("string == null: " + (string == null)); System.out.println("number
๐ŸŒ
Errorprone
errorprone.info โ€บ bugpattern โ€บ EqualsNull
EqualsNull
either returns false, or throws a NullPointerException if x is null. The nested block may never execute. This check replaces x.equals(null) with x == null, and !x.equals(null) with x != null.
๐ŸŒ
Educative
educative.io โ€บ answers โ€บ what-is-objectsequals-in-java
What is Objects.equals in Java?
The equals() method is a static method of the Objects class that accepts two objects and checks if the objects are equal. If both the objects point to null, then equals() returns true.
๐ŸŒ
DeepSource
deepsource.com โ€บ directory โ€บ java โ€บ issues โ€บ JAVA-E0110
`equals` method does not handle null valued operands (JAVA-E0110) ใƒป Java
ld throw `NoSuchElementException`JAVA-W0146Map compute methods cannot be used to create null valued entriesJAVA-W1011Audit: Double checked locking is not safeJAVA-E1018Static methods should be accessed using the class instanceJAVA-W1029`equals()` method parameters should not be marked with `@NotNull` or equivalent annotationsJAVA-W1028Basic authorization is a security riskJAVA-S1019Sealed class/interface permitted types need not be listed if they are declared in the same fileJAVA-W1031Boxed Boolean values should not be used in conditional expressionsJAVA-E1054@NoAllocation annotated methods sh
Top answer
1 of 1
14

First up, yes, you're right that the second null check is redundant. If obj is null then the method will return false on the first check:

    if (!(obj instanceof ArrayOfColumn)) return false;

Of course, that would better be written:

    if (!(obj instanceof ArrayOfColumn)) {
        return false;
    }

But, that's the least of my concerns. The synchronized equals is probably there because other methods are synchronized, but synchronization comes at a cost. Unless you are sure you need it, remove it.

Additionally, synchronized methods are seldom the best solution. It is normally better to have tighter control of your locks so that nobody but you can hold them. That normally means using a private, internal "monitor" for synchronization:

private final Objct lock = new Object();

private boolean equals(Object obj) {
    synchronized(lock) {
        .....
    }
}

Using the private lock prevents other people from hanging your application by using your class as their own monitor. Imagine if your class is called MyClass, and someone does:

 private MyClass instance = new MyClass();

 synchronized(instance) {
     Thread.sleep(10000);
 }

If they did the above, your methods in other threads would never run, and your application would "hang".

Now, abut the __equalsCalc variable. It does nothing useful. It is set, and then cleared, inside the synchronized method, and, as a result, it will never, ever have any value in it that is useful. It is completely redundant and a waste of time.

Oh, and what's with the fully qualified java.lang.Object? Just use Object.

I would rewrite the method as (using the same synchronized method to be compatible with other methods in your class):

public synchronized boolean equals(Object obj) {
    if (!(obj instanceof ArrayOfColumn)) {
        return false;
    }
    if (obj == this) {
        return true;
    }
    ArrayOfColumn other = (ArrayOfColumn) obj;
    if (getColumn() == null) {
        return other.getColumn() == null;
    }
    return other.getColumn() != null && Arrays.equals(column, other.getColumn());
}

Note that you still have a synchronization vulnerability - the other column's column could be changed between checking for whether it's column is null, and using the column in the equals. You could still get null pointer exceptions if someone changes the other column in the middle of your equals. You should consider synchronizing on that other column too:

public synchronized boolean equals(Object obj) {
    if (!(obj instanceof ArrayOfColumn)) {
        return false;
    }
    if (obj == this) {
        return true;
    }
    ArrayOfColumn other = (ArrayOfColumn) obj;
    synchronized(other) {
        if (getColumn() == null) {
            return other.getColumn() == null;
        }
        return other.getColumn() != null && Arrays.equals(column, other.getColumn());
    }
}

Unfortunately, cross-synchronizing like that can lead to deadlocks if you are not careful.

๐ŸŒ
Coderanch
coderanch.com โ€บ t โ€บ 523760 โ€บ java โ€บ null-null-java
null==something vs something==null in java (Beginning Java forum at Coderanch)
The long answer is that this is a remains from the old C days where everything could be treated as a boolean. If you forgot one of the = signs you would get an assignment. With something = null that assignment would succeed and the result would be equal to false.
๐ŸŒ
TutorialsPoint
tutorialspoint.com โ€บ comparing-strings-with-possible-null-values-in-java
Comparing Strings with (possible) null values in java?
In the same way the equals() method of the object class accepts two String values and returns a boolean value, which is true if both are equal (or, null) and false if not. import java.util.Scanner; public class CompringStrings { public static void main(String args[]) { Scanner sc = new ...
๐ŸŒ
Medium
medium.com โ€บ @thilinajayawardana_85346 โ€บ java-string-nullpointerexception-safe-equals-check-404481934e9b
Java String NullPointerException safe equals check | by Thilina Jayawardana | Medium
June 30, 2020 - In that case, you are always invoking the equals method of a String that you are pretty sure it exists. Usually, it could be a constant or a new String object. If you are not really sure either of them exists, so you better to check for null for the String that you are trying to invoke the equals method of.
๐ŸŒ
Quora
quora.com โ€บ Why-is-null-null-true-in-java
Why is null == null true in java? - Quora
Answer (1 of 8): In java only references can have the value null. As per the Java Language Specification it's "merely a special literal that can be of any reference type". For references == returns true if and only if the value of the two references are the same (or informally "they point to the...