The documentation for Class<T>.getConstructors()
reveals the issue:
Constructor<?>[] getConstructors()
: Note that while this method returns an array of Constructor<T>
objects (that is an array of constructors from this class), the return type of this method is Constructor<?>[]
and not Constructor<T>[]
as might be expected. This less informative return type is necessary since after being returned from this method, the array could be modified to hold Constructor
objects for different classes, which would violate the type guarantees of Constructor<T>[]
.
Compare this with Class<T>.getConstructor()
overload:
Constructor<T> getConstructor(Class<?>... parameterTypes)
This overload actually returns Constructor<T>
.
In your case, since you have Class<? extends Algorithm> alg
, alg.getConstructor(parameterTypes)
returns a Constructor<? extends Algorithm>
(which by the way, can NOT be safely cast to Constructor<Algorithm>
).
Whenever possible, i.e. when you know the parameter types, you should always prefer getConstructor(parameterTypes)
to getConstructors()[arbitraryIndex]
, since with the latter you're never quite guaranteed which constructor will be selected. Selecting based on parameter types is most specific, and as shown here, is also more compiler-friendly with regards to the generic type information.
If by getConstructors()[0]
you really meant to get the nullary constructor, then simply do this instead:
Constructor<? extends Algorithm> nullaryConstructor = alg.getConstructor();
Summary
So your problem was two fold:
getConstructors()
returns a Constructor<?>[]
, meaning all type information are lost
- Even if type information isn't lost (e.g. by using
getConstructor(parameterTypes)
overload), you'd still only get a Constructor<? extends Algorithm>
at best (not a Constructor<Algorithm>
).
Class<T>.getConstructor(parameterTypes)
returns a Constructor<T>
- In your case, the type parameter
T
is ? extends Algorithm
See also
Related questions
Discussion
It is unfortunate that getConstructors()
returns an array because as explained in the dcoumentation, because since arrays covariant, this forced the signature to Constructor<?>
, losing generic type information. The fact that arrays are mutable also means that getConstructors()
must create a new array instance every time!
System.out.println(int.class.getConstructors().length); // prints "0"
System.out.println(
int.class.getConstructors() == int.class.getConstructors()
); // prints "false"!
Ideally getConstructors()
should return a List<Constructor<T>>
, which should be wrapped by Collections.unmodifiableList
; not only would this keep the type information, but Class<T>
could also then return the same List
object on every getConstructors()
.
For more discussion on this subject, read Effective Java 2nd Edition, Item 25: Prefer lists to arrays.