This post describes a way to implement the equals hashCode and toString methods with relative brevity using Java 8 and KλudJe.
Plain Old Java Object
Consider this simple, three property type:
import java.time.LocalDate; import java.util.Objects; public class PersonPojo { private final long id; private final String name; private final LocalDate dateOfBirth; public PersonPojo(long id, String name, LocalDate dateOfBirth) { this.id = id; this.name = name; this.dateOfBirth = dateOfBirth; } public String getName() { return name; } public LocalDate getDateOfBirth() { return dateOfBirth; } @Override public boolean equals(Object o) { if (this == o) return true; if (!(o instanceof PersonPojo)) return false; PersonPojo that = (PersonPojo) o; return id == that.id && Objects.equals(name, that.name) && Objects.equals(dateOfBirth, that.dateOfBirth); } @Override public int hashCode() { int result = (int) (id ^ (id >>> 32)); result = 31 * result + Objects.hashCode(name); result = 31 * result + Objects.hashCode(dateOfBirth); return result; } @Override public String toString() { return "PersonPojo {" + id + ", " + name + ", " + dateOfBirth + '}'; } }
The hash could also be generated using Objects.hash(id, name, dateOfBirth)
but this comes at the cost of autoboxing a primitive and allocating an array for the method varargs.
If the type is modified (say to add another property) then the developer must remember to update the all three methods.
Defining significant properties with lambdas
Java 8 doesn't provide property references but they can be created easily enough. Here is an updated version of the above class:
import uk.kludje.Meta; import java.time.LocalDate; public class PersonPojo { private static final Meta<PersonPojo> META = Meta.<PersonPojo>meta() .longs($ -> $.id) .objects($ -> $.name, $ -> $.dateOfBirth); private final long id; private final String name; private final LocalDate dateOfBirth; public PersonPojo(long id, String name, LocalDate dateOfBirth) { this.id = id; this.name = name; this.dateOfBirth = dateOfBirth; } public String getName() { return name; } public LocalDate getDateOfBirth() { return dateOfBirth; } @Override public boolean equals(Object obj) { return META.equals(this, obj); } @Override public int hashCode() { return META.hashCode(this); } @Override public String toString() { return META.toString(this); } }
The expression $ -> $.id
is basically shorthand for:
new LongGetter<PersonPojo> () { @Override public long getLong(PersonPojo person) { return person.id; } }
Implementing these methods this way allows the specification of significant properties a single time and avoids the creation of extraneous objects, reflection or any preprocessing.
The KλudJe library is available here.
Alternatives
For experienced Java developers this topic is as old as the hills. Various static utilities, builders, reflective types and preprocessors are provided by Guava, Apache Commons Lang and Lombok.
No comments:
Post a Comment
All comments are moderated