Sponsored Link •
|
Summary
Pojomatic 2.0 has been released, and uses InvokeDynamic to give performance nearing that of hand-rolled code.
Advertisement
|
Version 2.0 of Pojomatic has
been released. Pojomatic provides an easy way to implement
the equals(Object)
, hashCode()
and toString()
methods inherited
from java.lang.Object
.
This release targets Java 7 or higher. The reason for this is to take advantage of the new InvokeDynamic instruction introduced in Java 7. While Pojomatic 1.0 used reflection to do it's work, this new version generates byte code using ASM, and uses InvokeDynamic to be able to access potentially private members of pojomated classes. The result is that the performance of equals and hashCode is now close to that of what would be seen with hand-rolled code. (To learn more about how this is done, come see my JavaOne talk this year).
Starting in Java 7, reflection no longer will necessarily return a class's elements in any particular order. Consequently, this release also uses ASM to read in the class file for a pojomated class, in order to determine the original order of fields and methods on the class.
import org.pojomatic.Pojomatic; import org.pojomatic.annotations.AutoProperty; @AutoProperty // tells Pojomatic to use all non-static fields. public class Pojo { // Fields, getters and setters... @Override public boolean equals(Object o) { return Pojomatic.equals(this, o); } @Override public int hashCode() { return Pojomatic.hashCode(this); } @Override public String toString() { return Pojomatic.toString(this); } }
While this is adequate more most cases, there are numerous ways to
customize how Pojomatic will build up the implementations of
the equals
, toString
and hashCode
methods. The
@AutoProperty
annotation can instruct Pojomatic to use fields or getters to accesses
properties. Alternatively, one can annotate individual fields and/or
accessor methods with the
@Property
annotation to include them explicitely, or to exclude certain
properties if @AutoProperty
is being used. For any
property, a
@PojomaticPolicy
can be set to indicate which methods the property should be included
in. By default, a property is used
for each of the equals
, hashCode
and toString
methods, but any combination is possible,
subject to the restriction that if a property is used
for hashCode
, then it must be used
for equals
as well.
As discussed in
How to
Write an Equality Method in Java, challenges arise in
satisfying the contract for equals
when class hierarchies
come into play. The solution suggested in that article is to
introduce an additional method, canEqual
, which the
implementation of equals
will use to ensure that
instances of a parent class do not accidentally declare themselves to
be equal to an instance of a subclass which has
redefined equals
. If all the classes in a hierarchy use
Pojomatic, this step is not necessary; Pojomatic keeps track of
whether instances of two related classes can be equal to each other or
not via the
areCompatibleForEquals
method. Two classes are compatible for
equality if they each have the same set of properties designated for
use with the equals
method. If a subclass has a need to
implement the equals
method without using Pojomatic, it
can be annotated with
@OverridesEquals
to indicate that it is not compatible for equality with it's parent class.
A common use of the equals
method is to facilitate the use
of the assertEquals
methods of JUnit or TestNG.
When assertEquals
fails, the exception method includes
the toString
representation of each instance. One pain point which no
doubt will be familiar to many is that of trying to determine why two
instances are not equal when they have a large number of properties.
Often, the only option is to copy the failure message into an editor
which allows comparing the toString
representations to look for
differences. Pojomatic helps address this by adding
method, Pojomatic.diff
which can reveal the differences between two instances of a Pojomated
class.
The PojomaticTestUtils
library leverages this capability to provide
an assertEqualsWithDiff
method which will call out the
differences between two instances in the failure messaged in the event
that they are not equal.
Pojomatic is available on the central maven repository; if you use maven, it is just a dependency away:
<dependency> <groupId>org.pojomatic</groupId> <artifactId>pojomatic</artifactId> <version>1.0</version> </dependency>Others can download Pojomatic from the central maven repository.
Have an opinion? Be the first to post a comment about this weblog entry.
If you'd like to be notified whenever Ian Robertson adds a new entry to his weblog, subscribe to his RSS feed.
Ian Robertson is an application architect at Verisk Health. He is interested in finding concise means of expression in Java without sacrificing type safety. He contributes to various open source projects, including jamon and pojomatic. |
Sponsored Links
|