Bahattin Ungormus
Bahattin Ungormus

Reputation: 723

How can I find a constructor without knowing its formal parameter types?

I want to create an instance of a class via reflection, and I know the given constructor parameters are compatible with the constructor. Though I do not have the formal parameter types of the constructor.

I know I can go through all constructors of the class to do this, but is there a more direct way in standard Java 8 API?

Upvotes: 1

Views: 133

Answers (2)

payloc91
payloc91

Reputation: 3809

If with Java 8 API means using streams you can do:

public static <T> T createInstance(Class<T> clz, Object... params) throws Exception {
    Class<?>[] c = Arrays
            .stream(params)
            .map(Object::getClass)
            .toArray(Class<?>[]::new);

    return clz.getConstructor(c).newInstance(params);
}

Test:

public static void main(String... args) throws Exception {
    String s = createInstance(String.class, (Object) new char[] {'h', 'e', 'l', 'l', 'o'});
    System.out.println(s);
}

Output:

hello

Basically the same as the other answer though, maybe a bit more elegant...

My function will fail for primitive types, as I can't get Integer.TYPE from a generic type.

Upvotes: 1

ernest_k
ernest_k

Reputation: 45339

If the runtime classes of your parametes match exactly the declared type of constructor parameters, you can build the corresponding array of Class instances, then look up the constructor:

public static void main(String[] args) throws Exception {
    Object[] params = new Object[] {Integer.valueOf(2), "name"};
    Class<?> cls[] = new Class<?>[params.length];
    List<Class<? extends Object>> classes = 
           Arrays.asList(params).stream().map(p -> p.getClass())
                 .collect(Collectors.toList());
    for(int i = 0; i < params.length; i++) {
        cls[i] = classes.get(i);
    }
    Person.class.getConstructor(cls)
    .newInstance(params);
}

That would work with a constructor declared as in this example:

class Person {
    public Person(Integer i, String name) {
        System.out.println("i: " + i + " name: " + name);
    }
}

That prints:

i: 2 name: name

Upvotes: 3

Related Questions