Reputation: 93
Does Lombok @EqualsAndHashCode check class type/instance?
Edit: I'd like to mention that I work for a major company with their own framework, like many other companies, that we are restricted to. I do not have the ability to add libraries outside of our framework due to how intensive our security needs to be (many of you wouldn't have electricity in your state). So Lombok was just introduced into our framework recently (version 1.18.12 which wasn't even released until 2/20) as was Java 8 to give you another example of what I'm working with and the code/libraries I may have been exposed to. So please forgive me if I'm not extremely well versed in Lombok or that I've never heard of Delombok until it was mentioned in the comments.
Back to the question:
I've read https://projectlombok.org/features/EqualsAndHashCode a few times and I keep coming out of it with different conclusions.
Here's an example of what I'm doing to help clarify my question:
@Entity
@Table(name = GeneratorTypeA.VIEW)
@Getter
@Setter
@ToString
@EqualsAndHashCode(callSuper = false, onlyExplicitlyIncluded = true)
public class GeneratorTypeA extends AbstractGenerator {
...
@Id
@EqualsAndHashCode.Include
@SequenceGenerator(...)
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "GeneratorA.seq.id")
@Column(name = "GENERATOR_A_ID", precision = 19, scale = 0)
private Long id;
...
}
GeneratorTypeB would look exactly the same as the above code snippet. Now say I have the following:
final Set<GeneratorTypeA> generatorsA = ...;
final Set<GeneratorTypeB> generatorsB = ...;
Each entity only uses @EqualsAndHashCode.Include on the "id" parameter. I am using the below code to combine Set and Set into a single Set. Since I only explicitly wrote that the unique id should be used for equals, I could lose entities from both sets when I combine them unless Lombok also compares the "instance of" each object. So does anyone know if Lombok does this check (with onlyExplicitlyIncluded set to true - or in general) or if there is a way to utilize Lombok with the addition of this check?
Equivalent equals method I'd want to use without Lombok:
public boolean equals(final Object other) {
if (!(other instanceof GeneratorTypeA)) {
return false;
}
final GeneratorTypeA castOther = (GeneratorTypeA) other;
return new EqualsBuilder().append(getId(), castOther.getId()).isEquals();
}
The code I'm using to combine the sets works fine with this setup, but I'm working with a lot of data so the chances of running into duplicate unique identifiers used in the equals method is very low, but it opens the door for unintended functionality/bugs.
public static <T> Set<?> combine(final Set<?>... sets) {
return Stream.of(sets).flatMap(Set::stream).collect(Collectors.toSet());
}
Upvotes: 0
Views: 1672
Reputation: 425458
Yes; the object is required to be an instance of this
class.
As per the documentation:
if (!(o instanceof EqualsAndHashCodeExample)) return false;
As an aside, it is ironic that your company is apparently so security conscious that it chose to wait many years before adopting java 1.8, but it waited so long that 1.8 was already end of life before you adopted it and support had already been terminated, leaving you exposed to unpatched security vulnerabilities.
Upvotes: 1
Reputation: 1271
Lombok, generates equals and hashcode very well and you should not worry about that. However you should take care when you override equals and hashcode and you use these objects in the Hash type collections and (this is important to know) the objects are not immutable. Then you might have unexpected results. Let me show you with a concrete example:
public class SetTest {
@Getter
@Setter
@AllArgsConstructor
@EqualsAndHashCode
@ToString
static class User {
private String name;
private int age;
}
public static void main(String[] args) {
Set<User> users = new HashSet<>();
User user1 = new User("Jane", 25);
User user2 = new User("John", 40);
users.add(user1);
users.add(user2);
user1.setAge(26);
users.add(user1);
System.out.println(users);
}
}
Answer: [Task.SetTest.User(name=Jane, age=26), Task.SetTest.User(name=Jane, age=26), Task.SetTest.User(name=John, age=40)]
As you can see, now you have in the set 3 objects instead of 2. This is happening because of the implementation of add from HashSet which works in this way:
In my case, after I changed the age of the user Jane, I changed the value of the hashcode, and the object was added in the collection because no other object with the same hashcode existed in the set.
Upvotes: 0