Lombok hashCode:: 1. Why good? 2. Why no compile error?

Advertisements

I have the following simple Java code,

import lombok.EqualsAndHashCode;

@EqualsAndHashCode
public class Test{
}

When I look at the delomboked code generated I see the following:

public class Test {
    public Test() {
    }

    public boolean equals(Object o) {
        if (o == this) {
            return true;
        } else if (!(o instanceof Test)) {
            return false;
        } else {
            Test other = (Test)o;
            return other.canEqual(this);
        }
    }

    protected boolean canEqual(Object other) {
        return other instanceof Test;
    }

    public int hashCode() {
        int result = true;
        return 1;
    }
}

I don’t understand the implementation of the hashCode(). How is this a good hashing method? And why is there no compile problem with int result = true;?

I suspect this is related to hashCode() being native, but I don’t understand why I see this implementation.


UPDATE: My main question is in regards to the lack of compile error. If I add two fields for example I would have:

import lombok.EqualsAndHashCode;

@EqualsAndHashCode
public class Test{
    private String name;
    public int age;
}

and

...

public int hashCode() {
        int PRIME = true;
        int result = 1;
        int result = result * 59 + this.age;
        Object $name = this.name;
        result = result * 59 + ($name == null ? 43 : $name.hashCode());
        return result;
    }

...

>Solution :

That you see the hashCode() method like this is probably an artifact of the tool you use to analyze the generated bytecode.

Internally the boolean values true and false are represented by the values 1 and 0 respectively. Some bytecode decompilers blindly translate 0 into false and 1 into true – this is what seems to be happening in your case.

The hashCode() method should read as

public int hashCode() {
    int result = 1;
    return 1;
}

Now to the question:

Is this a valid hashCode implementation?

Sure it is. The contracts for equals() and hashCode() state that for any two objects o1 and o2 when o1.equals(o2) is true then it must also be that o1.hashCode() == o2.hashCode().

Lomboks @EqualsAndHashCode annotation generates code so that two objects having the same field values are deemed equal (and therefore must have the same hashCode).

Since your class doesn’t have any fields, all instances are considered equal and therefore must have the same hashCode. The actual value of the hashCode doesn’t matter, as long as it is the same value for all instances.


Is the code that you see an error in the decompiler?

Yes, it clearly is (because the decompiler generates invalid source code).

Lombok itself contains an integrated "delombok" feature (https://projectlombok.org/features/delombok) and that feature creates for your first Test class the following source code (using Lombok 1.18.22):

public class Test {
    @Override
    public boolean equals(final Object o) {
        if (o == this) return true;
        if (!(o instanceof Test)) return false;
        final Test other = (Test) o;
        if (!other.canEqual((Object) this)) return false;
        return true;
    }

    protected boolean canEqual(final Object other) {
        return other instanceof Test;
    }

    @Override
    public int hashCode() {
        final int result = 1;
        return result;
    }
}

Leave a ReplyCancel reply