Taiga
Taiga

Reputation: 131

The functionality of the || operator

I have created an equals method. I believe I can do it in two ways but java doesn't seem to agree. Here is the first example which I know works.

    public class HelloWorld {

     public boolean equals(Object rhs){
        if(this==rhs){
            return true;
        }else if( rhs==null || this.getClass() != rhs.getClass()){
            return false;
        }else{

            HelloWorld tmp =(HelloWorld)rhs;
            return true;
        }
     }

     public static void main(String[] args){
        HelloWorld c = new HelloWorld();
        System.out.println(c.equals(null));

     }  
}

And here is the second example which doesn't work. Instead of returning false I get a nullpointerexception.

    public class HelloWorld {

     public boolean equals(Object rhs){
        if(this==rhs){
            return true;
        }else if(this.getClass() != rhs.getClass() || rhs==null){
            return false;
        }else{

            HelloWorld tmp =(HelloWorld)rhs;
            return true;
        }
     }

     public static void main(String[] args){
        HelloWorld c = new HelloWorld();
        System.out.println(c.equals(null));

     }  
}

My question then... The only difference between the two pieces of code is that in the first piece I've written

    rhs ==null ||...

And in the second piece it's on the other side of the OR-operator so

    ...|| rhs==null

Why would the first case not give me a Nullpointer but the second case does? Why should it matter on which side of the OR operator i write the boolean statement?

Upvotes: 3

Views: 123

Answers (4)

Abhi
Abhi

Reputation: 384

As you are using '||' which is conditional OR with short-circuit behavior, the second condition is not been evaluated if the first comes out to be true.

For example if you are using (A||B) --- if A is true, B will not be evaluated.

that's why you are getting Null Pointer exception in case rhs is null.

The first set of code is actually correct as you are correctly handling Null case over there, which is not with the case of second set.

If you want both conditions to be evaluated and don't want to have short circuit behavior, you can use '|' operator instead of '||'.

So in case of (A|B) ---even if A is true, B will be evaluated.

Upvotes: 0

duffymo
duffymo

Reputation: 308763

I would recommend that you follow Joshua Bloch's recipe for proper implementation of the equals method from his "Effective Java" chapter 3.

If you implement equals, you should also implement hashCode.

Upvotes: 1

Jon Skeet
Jon Skeet

Reputation: 1500515

The right-hand side of the || operator isn't executed if the left-hand side evaluates to true, as per JLS section 15.24:

The conditional-or operator || operator is like | (§15.22.2), but evaluates its right-hand operand only if the value of its left-hand operand is false.

So in your first case, rhs == null evaluates to true, so rhs.getClass() isn't executed - otherwise it would have thrown a NullPointerException.

In your second case, you're executing rhs.getClass() unconditionally, hence the exception.

If you use | instead of ||, you'll get an exception in both cases.

Upvotes: 2

rgettman
rgettman

Reputation: 178263

It matters because ||, being the conditional "OR" operator, won't evaluate the right expression if the left expression is true, because the result can already be determined. This is known as "short-circuit" behavior.

Section 15.24 of the JLS covers this:

The conditional-or operator || operator is like | (§15.22.2), but evaluates its right-hand operand only if the value of its left-hand operand is false.

The right hand expression is not evaluated, so the NullPointerException is avoided.

(The && conditional "AND" operator, also "short circuits" and will only evaluate the right side if the left side is true.)

Upvotes: 6

Related Questions