Sviatoslav Melnychenko
Sviatoslav Melnychenko

Reputation: 543

Java | Get constructor reflectively

How I can get constructor reflectively, if its param is Object ... objects.

My constructor:

  public MyClass ( Object ... objects )
  {
    if ( ! ( objects == null ) )
    {
      if ( objects.length > 0 && objects [ 0 ] instanceof Long )
      {
        setLatency ( ( Long ) objects [ 0 ] ) ;
      }
    }
  }

How I get it now:

Class< ? > clazz = Class.forName ( "MyClass" ) ;

Constructor< ? > clazzConstructor = clazz.getConstructor ( Object [ ].class ) ;

What I try to do:

Long latency = 1000L ;

MyClass myInstance = ( MyClass ) clazzConstructor.newInstance ( latency ) ;

And I get java.lang.IllegalArgumentException: argument type mismatch

If latency == null, everything works.

Upvotes: 2

Views: 2626

Answers (2)

Pshemo
Pshemo

Reputation: 124225

Try it this way

MyClass myInstance = (MyClass) clazzConstructor
        .newInstance(new Object[] { new Object[] { latency } });

newInstance(Object ... initargs) needs array of objects as arguments. Buy your fist argument in constructor is also array of object Object... o so you need to wrap it again in Object array.

I tested it with this code and in seems to work fine

class MyClass {
    private Long latency;

    public void setLatency(Long latency) {
        this.latency = latency;
    }
    public Long getLatency() {
        return latency;
    }

    public MyClass(Object... objects) {
        if (!(objects == null)) {
            if (objects.length > 0 && objects[0] instanceof Long) {
                setLatency((Long) objects[0]);
            }
        }
    }

    public static void main(String[] args) throws Exception {
        Class<?> clazz = MyClass.class;

        Constructor<?> clazzConstructor = clazz.getConstructor(Object[].class);
        System.out.println(clazzConstructor);

        Long latency = 1000L ;
        MyClass myInstance = (MyClass) clazzConstructor
                .newInstance(new Object[] { new Object[] { latency } });
        System.out.println(myInstance);
        System.out.println(myInstance.getLatency());
    }
}

Upvotes: 7

biziclop
biziclop

Reputation: 49744

Your constructor is expecting an object array but you're passing a single Long to it.

Wrapping latency into an object array will work, although be careful as newInstance() itself is expecting Object ..., and if you pass it nothing but an Object[], it will interpret it as a list of arguments. So you'll have to do something like this:

MyClass myInstance = ( MyClass ) clazzConstructor.newInstance ( (Object)new Object[] { latency } ) ;

or

MyClass myInstance = ( MyClass ) clazzConstructor.newInstance ( new Object[] { new Object[] { latency } } ) ;

The first one "fools" the compiler into wrapping your object array into another, the second one does it explicitly instead.

(Passing null only worked because null is null, no matter what the declared type of the parameter is.)

Upvotes: 8

Related Questions