Java 7 was released in 2011 and brought to us, programmers, several interesting features as diamond operators or new I/O library. Yet another useful thing is less popular than two cited previously - Objects tool class.
Data Engineering Design Patterns

Looking for a book that defines and solves most common data engineering problems? I wrote
one on that topic! You can read it online
on the O'Reilly platform,
or get a print copy on Amazon.
I also help solve your data engineering problems 👉 contact@waitingforcode.com 📩
In this article we'll present all features included in this static tool class. Roughly it's a great alternative for Objects class from Google Guava and Apache Commons builders (org.apache.commons.lang.builder) for equals() and hashCode() methods.
Before we start, there are common parts for each made tests:
public class ObjectsTest { private TestedObject tested1 = new TestedObject("Abc", 39); private static class TestedObject { private String name; private int age; public TestedObject(String name, int age) { this.name = name; this.age = age; } public String getName() { return this.name; } public Integer getAge() { return this.age; } @Override public int hashCode() { return Objects.hash(getName(), getAge()); } @Override public boolean equals(Object compared) { if (!(compared instanceof TestedObject)) { return false; } TestedObject testedObject = (TestedObject) compared; return Objects.equals(getAge(), testedObject.getAge()) && Objects.equals(getName(), testedObject.getName()); } @Override public String toString() { return MoreObjects.toStringHelper(this).add("name", name).add("age", age).toString(); } } private static class TestedObjectComparator implements Comparator<TestedObject> { @Override public int compare(TestedObject tested1, TestedObject tested2) { return ComparisonChain.start().compare(tested1.getName(), tested2.getName()) .compare(tested1.getAge(), tested2.getAge()) .result(); } } }
Comparing with Objects class
We'll begin by comparison of objects, as well through comparators as through equals() functions. Objects provides 3 methods which can help us to compare:
- equals(Object a, Object b): it's used to check if two objects are equal.
- deepEquals(Object a, Object b): as equals() but can be applied to "deep" objects as arrays.
- compare(Object a, Object b, Comparator c): compares two objects using given comparator
There are some samples of these methods use:
// equality cases @Test public void testEquality() { // To check equality with Objects.equals() method, compared objects must implement equals() // And in fact, the real utility of Objects.equals() method is inside implemented equals method where, to check // if two objects are equal, we very often compare its attributes. TestedObject tested1Prime = new TestedObject("Abc", 39); assertThat(Objects.equals(tested1, tested1Prime)).isTrue(); } @Test public void testEqualityNotEquals() { TestedObject tested2 = new TestedObject("abc", 39); assertThat(Objects.equals(tested2, tested1)).isFalse(); } @Test public void testEqualityForNullObjects() { // When one of compared Objects is null, we consider that both are not equal TestedObject tested3 = new TestedObject(null, 39); assertThat(Objects.equals(tested3, tested1)).isFalse(); } @Test public void testEqualityForBothNullObjects() { TestedObject testedWithNull1 = new TestedObject(null, 39); TestedObject testedWithNull2 = new TestedObject(null, 39); assertThat(Objects.equals(testedWithNull1, testedWithNull2)).isTrue(); } @Test public void testDeepEqualityForEqualArrays() { // deep equality test method is very useful for arrays; it uses Arrays.deepEquals method which, according to the // Javadoc http://docs.oracle.com/javase/7/docs/api/java/util/Arrays.html#deepEquals(java.lang.Object[],%20java.lang.Object[]), // checks the equality in several aspects TestedObject tested2 = new TestedObject("XYZ", 40); TestedObject tested3 = new TestedObject("JKL", 50); TestedObject[] testedArray1 = new TestedObject[] {tested1, tested2, tested3}; TestedObject[] testedArray2 = new TestedObject[] {tested1, tested2, tested3}; assertThat(Objects.deepEquals(testedArray1, testedArray2)).isTrue(); assertThat(Objects.equals(testedArray1, testedArray2)).isFalse(); } @Test public void testDeepEqualityForNotEqualArrays() { TestedObject tested2 = new TestedObject("XYZ", 40); TestedObject tested3 = new TestedObject("JKL", 50); TestedObject[] testedArray1 = new TestedObject[] {tested1, tested2, tested3}; TestedObject[] testedArray2 = new TestedObject[] {tested1, tested2, null}; assertThat(Objects.deepEquals(testedArray1, testedArray2)).isFalse(); } @Test public void testDeepEqualityForNotTheSameLengthArrays() { TestedObject tested2 = new TestedObject("XYZ", 40); TestedObject tested3 = new TestedObject("JKL", 50); TestedObject[][] testedArray1 = new TestedObject[2][]; testedArray1[0] = new TestedObject[] {tested1, tested2}; testedArray1[1] = new TestedObject[] {tested2, tested3}; TestedObject[][] testedArray2 = new TestedObject[2][]; testedArray2[0] = new TestedObject[] {tested1}; testedArray2[1] = new TestedObject[] {tested2}; assertThat(Objects.deepEquals(testedArray1, testedArray2)).isFalse(); } @Test public void testDeepEqualityForTheSameMultiDimsArrays() { TestedObject tested2 = new TestedObject("XYZ", 40); TestedObject tested3 = new TestedObject("JKL", 50); TestedObject[][] testedArray1 = new TestedObject[2][]; testedArray1[0] = new TestedObject[] {tested1, tested2}; testedArray1[1] = new TestedObject[] {tested2, tested3}; TestedObject[][] testedArray2 = new TestedObject[2][]; testedArray2[0] = new TestedObject[] {tested1, tested2}; testedArray2[1] = new TestedObject[] {tested2, tested3}; assertThat(Objects.deepEquals(testedArray1, testedArray2)).isTrue(); } @Test public void testEqualityList() { ListtestedList1 = Arrays.asList("XYZ", "ABC"); List testedList2 = Arrays.asList("XYZ", "ABC"); assertThat(Objects.equals(testedList1, testedList2)).isTrue(); } @Test public void testEqualityListNotEquals() { List testedList1 = Arrays.asList("123", "ABC"); List<String> testedList2 = Arrays.asList("XYZ", "ABC"); assertThat(Objects.equals(testedList1, testedList2)).isFalse(); }
Generating hash codes with Objects class
Another features provided by Objects concern hash codes. Two methods were defined for them:
- hash(Object... values): generates numeric value which can be used as hash code of given object.
- hashCode(Object o): returns hash code of given object or 0 if the object is null.
Following test cases show how hash coding part can be used:
// hashCode cases @Test public void testHashCodeGeneration() { int hashCode123 = Objects.hash(3, "ABC", 123); int hashCode098 = Objects.hash(0, "ZYX", 980); int hashCode123Prime = Objects.hash(3, "ABC", 123); assertThat(hashCode123).isNotEqualTo(hashCode098); assertThat(hashCode123Prime).isEqualTo(hashCode123); } @Test public void testHashCodingOnNullObject() { int nullHashCode = Objects.hashCode(null); assertThat(nullHashCode).isEqualTo(0); } @Test public void testHashCodeOnNonNullObject() { int nonNullHashCode = Objects.hashCode(tested1); assertThat(nonNullHashCode).isGreaterThan(1); }
Checking objects with Objects class
Another interesting point are requireNotNull methods which check if given object is not null. According to the Javadoc, they're "designed primarily for doing parameter validation in methods and constructs with multiple parameters". Every time when checked object is null, NullPointerException is thrown:
- requireNonNull(T object): basic method which throws NPE.
- requireNonNull(T object, String message): extended method which throws NPE with specified message.
These three test cases should help to understand the difference between two requireNonNull methods:
// object checking cases @Test public void testRequiringNotNull() { // requireNonNull methods will check if provided object is not null and throw NullPointerException when it's null TestedObject testedNotNull = Objects.requireNonNull(tested1); assertThat(testedNotNull).isEqualTo(tested1); } @Test(expected = NullPointerException.class) public void testRequiringNotNullOnNullObject() { TestedObject nullTested = null; TestedObject testedNull = Objects.requireNonNull(nullTested); } @Test public void testRequireNonNullWithMessage() { TestedObject nullTested = null; String realNpeMessage = ""; String expectedMessage = "! Should not be null !"; try { Objects.requireNonNull(null, expectedMessage); } catch (NullPointerException npe) { realNpeMessage = npe.getMessage(); } assertThat(realNpeMessage).isEqualTo(expectedMessage); }
String tools
The last utility part introduced by Objects concerns toString method:
- toString(Object o): returns the result of toString() method of provided object. If the object is null, it returns a "null" String.
- toString(Object o, String defaultMsg): as previous, but instead of returning "null" for null object, it returns the text specified in defaultMsg parameter.
We can observe that in following test cases:
In this article we can discover the interesting features defined in Objects class. Thanks to it, we can, for example, avoid some overhead associated with null checking, as well as with implementing of several Object methods (hashCode, toString, equals).
Consulting
![]()
With nearly 16 years of experience, including 8 as data engineer, I offer expert consulting to design and optimize scalable data solutions. As an O’Reilly author, Data+AI Summit speaker, and blogger, I bring cutting-edge insights to modernize infrastructure, build robust pipelines, and drive data-driven decision-making. Let's transform your data challenges into opportunities—reach out to elevate your data engineering game today!
👉 contact@waitingforcode.com
đź”— past projects