chinabugotech/hutool · error · IllegalArgumentException

The object to build a hash code for must not be null

Error message

The object to build a hash code for must not be null

What it means

HashCodeBuilder.reflectionHashCode computes a hash by reflecting over the object's fields; a null object has no fields to read, so it is rejected immediately with IllegalArgumentException. The method also requires non-zero odd seed/multiplier numbers (validated elsewhere). This mirrors Apache Commons Lang's contract.

Source

Thrown at hutool-core/src/main/java/cn/hutool/core/builder/HashCodeBuilder.java:337

     *            the Object to create a <code>hashCode</code> for
     * @param testTransients
     *            whether to include transient fields
     * @param reflectUpToClass
     *            the superclass to reflect up to (inclusive), may be <code>null</code>
     * @param excludeFields
     *            array of field names to exclude from use in calculation of hash code
     * @return int hash code
     * @throws IllegalArgumentException
     *             if the Object is <code>null</code>
     * @throws IllegalArgumentException
     *             if the number is zero or even
     * @since 2.0
     */
    public static <T> int reflectionHashCode(final int initialNonZeroOddNumber, final int multiplierNonZeroOddNumber, final T object,
            final boolean testTransients, final Class<? super T> reflectUpToClass, final String... excludeFields) {

        if (object == null) {
            throw new IllegalArgumentException("The object to build a hash code for must not be null");
        }
        final HashCodeBuilder builder = new HashCodeBuilder(initialNonZeroOddNumber, multiplierNonZeroOddNumber);
        Class<?> clazz = object.getClass();
        reflectionAppend(object, clazz, builder, testTransients, excludeFields);
        while (clazz.getSuperclass() != null && clazz != reflectUpToClass) {
            clazz = clazz.getSuperclass();
            reflectionAppend(object, clazz, builder, testTransients, excludeFields);
        }
        return builder.toHashCode();
    }

    /**
     * <p>
     * Uses reflection to build a valid hash code from the fields of {@code object}.
     * </p>
     *
     * <p>
     * This constructor uses two hard coded choices for the constants needed to build a hash code.

View on GitHub (pinned to 8870454b2a)

Solutions

  1. Null-check before calling: return 0 (or Objects.hashCode) for null.
  2. Prefer Objects.hash / IDE-generated hashCode for performance-critical code; reserve reflectionHashCode for convenience.
  3. If building equals/hashCode, guard `if (obj == null) return false;` then hash.

Example fix

// before
public int hashCode() { return HashCodeBuilder.reflectionHashCode(17, 37, this, false); } // NPE risk if this ever null via static call
// after
public static int hashOf(MyType o) { return o == null ? 0 : HashCodeBuilder.reflectionHashCode(17, 37, o, false); }
Defensive patterns

Strategy: type-guard

Validate before calling

if (object == null) throw new IllegalArgumentException("object must not be null");

Type guard

static <T> boolean hashable(T o) { return o != null; }

Prevention

When it happens

Trigger: Calling HashCodeBuilder.reflectionHashCode(...) (any overload delegating here) with a null first-arg object. Common when building equals/hashCode pairs that forget the null branch before delegating.

Common situations: equals() implementations that call reflectionHashCode without first null-checking this/other; collections containing nulls that hash via this builder.

Related errors


AI-assisted analysis of chinabugotech/hutool@8870454b2a (2026-08-14). Data as JSON: /api/errors/ee842f4883cd55eb. Report an issue: GitHub.