skip to content

Utility Classes

The small JDK helper classes you should reach for instead of writing your own, chiefly java.util.Objects. Interviewers notice when you hand-roll a null-safe equals.

part ofJavaoverview, primer and where to startread it →
on this pageshow

questions

5

What does Objects.equals(a, b) do, and why prefer it over a.equals(b)?

level: juniorimportance: must knowfreq 70%

answer

  1. null == null is true, null vs non-null is false
  2. (a == b) || (a != null && a.equals(b))
  3. Never throws NPE on a null operand
  4. Arrays: use Arrays.equals / Objects.deepEquals instead
  5. Standard helper for comparing fields in equals()

basics

~20 s

Objects.equals(a, b) compares two values for equality but won't crash if either is null. It returns true if both are null, false if only one is, and otherwise calls a.equals(b). Plain a.equals(b) throws if a is null.

solid answer

~40 s

Objects.equals(a, b) is a null-safe equality helper. Its logic is: if a == b (same reference, including both null) return true; if a is null return false; otherwise return a.equals(b). So two nulls are equal, a null and a non-null are not, and non-nulls delegate to the left operand's equals. The win over a.equals(b) is that you never get a NullPointerException when a might be null, which is common with nullable fields. It's the idiomatic way to compare fields inside equals() implementations and to compare values that may legitimately be null (DB columns, optional inputs). Note it does NOT deep-compare arrays - for that use Arrays.equals or Objects.deepEquals.

go deeper

for a junior

Knows it as the null-safe way to compare values and that plain a.equals(b) can throw NPE.

for a middle

Can recite the (a==b)||(a!=null&&a.equals(b)) logic and uses it to implement equals() over nullable fields.

for a senior

Knows the array pitfall (reference identity) and reaches for Arrays.equals/Objects.deepEquals; understands it delegates to the left operand's equals.

for a principal

Discusses equals/hashCode contract integrity, symmetry caveats with broken equals, and sets team conventions for null-safe comparison and array handling.

## The problem it solves In Java, every object inherits an `equals(Object)` method used to test whether two objects are "equal" by value. You normally call it as `a.equals(b)`. But there is a trap: `null` is a valid value for any reference variable, and calling any method on `null` throws a `NullPointerException` (NPE) - the most common runtime error in Java. So `a.equals(b)` blows up the moment `a` happens to be `null`. This matters constantly because nullable values are everywhere: a field that hasn't been set, a database column that allows NULL, an optional method argument, a map lookup that missed. ## What Objects.equals does `java.util.Objects` is a tiny utility class (added in Java 7) full of static helper methods. `Objects.equals(Object a, Object b)` is one of them. Its exact behaviour is: ```java public static boolean equals(Object a, Object b) { return (a == b) || (a != null && a.equals(b)); } ``` Read it step by step: 1. `a == b` - reference identity. This is `true` when they are literally the same object, and crucially also `true` when **both are null** (two nulls are the same "reference"). So `Objects.equals(null, null)` returns `true`. 2. If that fails, `a != null && a.equals(b)` - we only reach `a.equals(b)` when `a` is definitely not null, so no NPE is possible. If `a` is non-null but `b` is null, the normal `equals` contract returns `false`. Net result: **null == null is true, null vs non-null is false, non-null delegates to a.equals(b)**, and it can never throw an NPE because of a null operand. ## Why not just write a.equals(b)? Because you'd have to guard every call yourself: `a == null ? b == null : a.equals(b)`. That's verbose, easy to get wrong, and clutters code. `Objects.equals` packages that idiom into one readable call. ## Where you use it - **Inside your own `equals()` methods**, to compare each field: `Objects.equals(this.name, other.name) && Objects.equals(this.email, other.email)`. Fields are often nullable, so this is the standard pattern. - **Anywhere you compare two possibly-null values** for logical equality. ## Important limitation: arrays `Objects.equals` for two arrays just calls `Object.equals`, which is **reference identity** for arrays (arrays don't override equals). So `Objects.equals(new int[]{1}, new int[]{1})` is `false`. For element-wise array comparison use `java.util.Arrays.equals(...)`, or `Objects.deepEquals(a, b)` which handles nested arrays. ## Relationship to hashCode The equals/hashCode contract says equal objects must have equal hash codes. When you use `Objects.equals` to build `equals()`, you typically pair it with `Objects.hash(...)` to build `hashCode()` (covered separately).

  • How would you correctly compare two int arrays for equal contents?
    Use Arrays.equals(a, b) for flat arrays, or Objects.deepEquals(a, b) / Arrays.deepEquals for nested arrays. Objects.equals would only check reference identity for arrays and return false for distinct-but-equal arrays.
  • Is Objects.equals symmetric - does the order of arguments matter?
    Logically it should be symmetric and is for correct equals implementations, but it delegates to the LEFT operand's equals. If a class has a broken (non-symmetric) equals, swapping arguments can change the result. The null handling itself is symmetric.

saying these in an interview costs you the question

  • Claiming Objects.equals deep-compares arrays element-by-element (it does not)
  • Saying Objects.equals(null, null) returns false
  • Thinking it can still throw NPE if the first arg is null
  • Confusing it with == for object value comparison

context

open as a page

What is Objects.requireNonNull and when should you use it for fail-fast null checks?

level: juniorimportance: must knowfreq 72%

basics

~20 s

Objects.requireNonNull(x) throws a NullPointerException immediately if x is null, otherwise returns x. You use it to validate arguments early - usually in constructors - so a bad null fails right away with a clear message instead of later somewhere confusing.

open as a page

How do you implement hashCode() using Objects.hash(...), and what are its caveats?

level: middleimportance: must knowfreq 68%

basics

~10 s

Objects.hash(field1, field2, ...) takes the fields that define equality and combines them into one int hash code. You return it from hashCode(): return Objects.hash(name, email);. It handles nulls automatically.

open as a page

How do Objects.requireNonNullElse and Objects.toString(obj, default) provide null-safe defaults, and how do they differ from requireNonNull?

level: middleimportance: should knowfreq 50%

basics

~20 s

requireNonNullElse(x, fallback) returns x if it's not null, otherwise the fallback - so you get a default instead of an exception. Objects.toString(obj, nullDefault) returns obj.toString() if obj isn't null, otherwise the given default string. Both substitute a value for null instead of throwing like requireNonNull does.

open as a page

Given nullable values, how do you decide between Objects.requireNonNull, requireNonNullElse, Objects.equals/hash, and Optional? Discuss the design trade-offs.

level: seniorimportance: should knowfreq 42%

basics

~20 s

Use requireNonNull when null means a bug and you want to fail fast; use requireNonNullElse when null is fine and you just want a default; use Objects.equals/hash to safely compare and hash nullable fields; use Optional mainly for return values that may be absent, not for parameters or fields.

open as a page