didi/DoKit · error · ReflectedException

Constructor was null!

Error message

Constructor was null!

What it means

Reflector.newInstance(Object...) throws ReflectedException("Constructor was null!") when the internal mConstructor field is null — i.e. newInstance is called before constructor(...) ever successfully selected one, or after a later field()/method() call reset mConstructor to null. It is a strict usage-ordering guard, not a JVM failure.

Source

Thrown at Android/dokit/src/main/java/com/didichuxing/doraemonkit/util/Reflector.java:81

    
    }
    
    public Reflector constructor(@Nullable Class<?>... parameterTypes) throws ReflectedException {
        try {
            mConstructor = mType.getDeclaredConstructor(parameterTypes);
            mConstructor.setAccessible(true);
            mField = null;
            mMethod = null;
            return this;
        } catch (Throwable e) {
            throw new ReflectedException("Oops!", e);
        }
    }
    
    @SuppressWarnings("unchecked")
    public <R> R newInstance(@Nullable Object ... initargs) throws ReflectedException {
        if (mConstructor == null) {
            throw new ReflectedException("Constructor was null!");
        }
        try {
            return (R) mConstructor.newInstance(initargs);
        } catch (InvocationTargetException e) {
            throw new ReflectedException("Oops!", e.getTargetException());
        } catch (Throwable e) {
            throw new ReflectedException("Oops!", e);
        }
    }
    
    protected Object checked(@Nullable Object caller) throws ReflectedException {
        if (caller == null || mType.isInstance(caller)) {
            return caller;
        }
        throw new ReflectedException("Caller [" + caller + "] is not a instance of type [" + mType + "]!");
    }
    
    protected void check(@Nullable Object caller, @Nullable Member member, @NonNull String name) throws ReflectedException {

View on GitHub (pinned to 626827cddb)

Solutions

  1. Always chain .constructor(parameterTypes) immediately before .newInstance(args)
  2. Do not interleave .field()/.method() between .constructor() and .newInstance() — they clear mConstructor
  3. Use a fresh Reflector.on(...) instance per member kind if you need several lookups

Example fix

// before
Reflector.on(cls).newInstance("arg");

// after
Reflector.on(cls).constructor(String.class).newInstance("arg");
Defensive patterns

Strategy: validation

Validate before calling

// ensure constructor is selected before newInstance
if (r == null /* or mConstructor unset */) { throw new IllegalStateException("call constructor(...) first"); }

Prevention

When it happens

Trigger: Calling Reflector.on(SomeClass.class).newInstance(...) directly without a preceding .constructor(...); or calling .field("x")/.method("y") after .constructor(...) (both null out mConstructor) and then newInstance again.

Common situations: Chained fluent calls reordered during refactoring; copy-paste of a reflect snippet that omitted the constructor step; interleaving constructor and field/method lookups on the same Reflector instance.

Related errors


AI-assisted analysis of didi/DoKit@626827cddb (2026-08-14). Data as JSON: /api/errors/c8e4bba0d94a8902. Report an issue: GitHub.