In Java 7, we'll see a new class : java.util.Objects. This class contains 9 static methods to work on Objects. I found these methods really useful.
First, two really simple methods to assert non-null objects in getter/setter (or other methods, of course) :
- T nonNull(T obj) : If obj is not null, return obj else throw a NullPointerException.
- T nonNull(T obj, String message) : If obj is not null return obj else throw a customized NullPointerException with the given message
Some simple examples :
public void setFoo(Foo foo){
this.foo = Objects.nonNull(foo);
}
public void setBar(Bar bar){
this.foo = Objects.nonNull(bar, "bar cannot be null");
}
Although simple, these methods can improve the readability of code and avoid having to write the is-null check ourselves.
Then, we have two methods to compute a toString() value for Object supporting null objects :
- String toString(Object o) : Return the toString() value of a non-null object otherwise "null".
- String toString(Object o, String nullDefault) : Return the toString() value of a non-null object otherwise return nullDefault
Again, this is useful for code readibility :
public class Bar {
private Foo foo;
private Bar parent;
@Override
public String toString(){
return "Bar {foo = " + Objects.toString(foo) + ", parent = " + Objects.toString(parent, "no parent, orphan") + "}";
}
}
I think, it's a lot better than :
public class Bar {
private Foo foo;
private Bar parent;
@Override
public String toString(){
return "Bar {foo = " + (foo == null ? "null" : foo.toString()) + ", parent = " + (parent == null ? "o parent, orphan" : parent.toString()) + "}";
}
}
Isn't it ?
After that, we also two similar methods for hashing :
- int hash(Object... values) : Compute a hash code for all the given values
- int hashCode(Object o) : If 0 is null return 0 othewise return o.hashCode()
If we take again the exemple of the Bar class. If we have to write the hashCode() method without Objects, we could do that :
public class Bar {
private Foo foo;
private Bar parent;
@Override
public int hashCode(){
int result = 17;
result = 31 * result + (foo == null ? 0 : foo.hashCode());
result = 31 * result + (parent == null ? 0 : parent.hashCode());
return result;
}
}
With Java 7, we only have to do that :
public class Bar {
private Foo foo;
private Bar parent;
@Override
public int hashCode(){
return Objects.hash(foo, parent);
}
}
And that's it :)
On the same model, we've also two methods for equality checks :
- boolean equals(Object a, Object b) : Return true if the two arguments are null or they are both not null and a.equals(b) return true, otherwise false.
- boolean deepEquals(Object a, Object b) : Almost the same as the first method except that if both a and b are arrays, the equality is evaluated using Arrays.deepEquals method.
Once again, that can really ease the coding of equals() methods :
public class Bar {
private Foo foo;
private Bar parent;
@Override
public boolean equals(Object obj){
if (obj == this) {
return true;
}
if (obj instanceof Bar) {
Bar other = (Bar) obj;
if (foo != other.foo) {
if (foo == null || !foo.equals(other.foo)) {
return false;
}
}
if (parent != other.parent) {
if (parent == null || !parent.equals(other.parent)) {
return false;
}
}
return true;
}
return false;
}
}
become :
public class Bar {
private Foo foo;
private Bar parent;
@Override
public boolean equals(Object obj){
if (obj == this) {
return true;
}
if (obj instanceof Bar) {
Bar other = (Bar) obj;
return Objects.equals(foo, other.foo) && Objects.equals(parent, other.parent);
}
return false;
}
}
Better, no ?
And the last one : int compare(T a, T b, Comparator<? super T> c). This method returns 0 if a == b or if both are null otherwise c.compare(a, b). The support of null is delegated to the comparator.
We've covered all the features offered by this new class.
Of course, there is already some methods like that in librairies like Jarkarta Commons or Google Guava, but it's always better when we doesn't have to include a library for that kind of features.
I hope you found this post interesting.