New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

@EqualAndHashCode problems with subclasses #1505

Closed
fo0 opened this Issue Oct 28, 2017 · 3 comments

Comments

Projects
None yet
3 participants
@fo0

fo0 commented Oct 28, 2017

I'v got problems with comparing a subclass with a superclass.
According to your doc, you generate the hashcode as follows:

@Override public int hashCode() {
      final int PRIME = 59;
      int result = 1;
      result =(result*PRIME) + super.hashCode();
      result = (result*PRIME) + this.width;
      result = (result*PRIME) + this.height;
      return result;
    }

The following line:
result =(result*PRIME) + super.hashCode();
modify the hashcode of the superclass, and if I use the annotation:
@EqualsAndHashCode(callSuper=true, of={})
I can't get the original hashcode of my superclass, to let the superclass and subclass be equal.
Because you always add the Prime to the hashcode

Is there an option to get the original hashcode from the superclass ?

My current workaround is to do it manually by adding the following lines:

@Override
public boolean equals(Object obj) {
        return super.equals(obj);
}

@Override
public int hashCode() {
	return super.hashCode();
}

But it could be nice, if there is an option to do it via your annotation
@EqualsAndHashCode(callSuper=true, prime=false, of={})
or
@EqualsAndHashCode(callSuper=true, prime=0, of={})
to set the prime generation number of 0

@Maaartinus

This comment has been minimized.

Contributor

Maaartinus commented Oct 29, 2017

This doesn't sound right. You're overriding both methods and achieve the same behavior as when you just leave them out. Would using no @EqualsAndHashCode in the subclass do?

Or are you using another annotation like @Data? Then @EqualsAndHashCode is implied and your manual overriding makes sense.

I don't like the options like prime=false or prime=0 as they're fixing something which should work out of the box. IMHO @EqualsAndHashCode(callSuper=true, of={}) is currently broken as it returns different hashcodes for equal objects.


I guess, the proper fix would be something like

@Override public int hashCode() {
      final int PRIME = 59;
      int result = callSuper ? super.hashCode() : 1
      result = (result*PRIME) + this.width;
      result = (result*PRIME) + this.height;
      return result;
    }

which reduces to

@Override public int hashCode() {
      final int PRIME = 59;
      int result = callSuper ? super.hashCode() : 1
      return result;
    }

when no fields are included. This only changes the broken behavior for callSuper=true.


A more conservative solution would be generating nothing (or trivial super-calling methods) when both callSuper=true is given and no fields are to be included (due to of ={} or lack of fields).

@fo0

This comment has been minimized.

fo0 commented Oct 29, 2017

yeah thats right. I just did a suggestions, because it could be that this prime is really wanted from the author. So its still configurable for the user, if he want to change this. At least, I would recommend your suggestions too:

@Override public int hashCode() {
      final int PRIME = 59;
      int result = callSuper ? super.hashCode() : 1
      return result;
    }
@rspilker

This comment has been minimized.

Collaborator

rspilker commented Nov 6, 2017

Acrually, the code is even simpler, since at code generation time we have the value of callSuper.

if (callSuper) {
    // generate 'int result = 1;'
} else {
    // generate 'int result = super.hashCode();'
}

Also, if no fields are present, we don't even need to create the final int PRIME = 59; anymore.

@rspilker rspilker closed this in 045638e Nov 6, 2017

rspilker added a commit that referenced this issue Nov 6, 2017

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment