The javadoc for Class::getDeclaredConstructor (http://docs.oracle.com/javase/8/docs/api/java/lang/Class.html#getDeclaredConstructor-java.lang.Class...-) says:
Returns a Constructor object that reflects the specified constructor of the class or interface represented by this Class object. [emphasis mine]
Since you can't declare a constructor for an interface, what could it mean to return a "specified constructor" of an interface?
I tried it on Runnable.class and got NoSuchMethodException. Is there a case where getDeclaredConstructor will work on an interface? Or is this language in the javadoc just an error? Or does it mean something other than how I'm interpreting it?
3 Answers
Answers 1
A call to Class.getConstructor will result in a call to Class.privateGetDeclaredConstructors to retrieve all declared constructors. The matching constructor is selected from that list:
private Constructor<T>[] privateGetDeclaredConstructors(boolean publicOnly) { ... // No cached value available; request value from VM if (isInterface()) { @SuppressWarnings("unchecked") Constructor<T>[] temporaryRes = (Constructor<T>[]) new Constructor<?>[0]; res = temporaryRes; } else { res = getDeclaredConstructors0(publicOnly); } ... return res; } (I removed part of the code which deals with cached constructors).
So for interfaces the constructor list is always empty and a NoSuchMethodException will always be thrown.
Answers 2
I don't consider this an error in javadoc. Class object can represent class or interface, there is no error in that statement.
If you're using reflection and explicitly ask for specific elements, you have to make sure that elements with the identification specified in the reflective calls exist. If you're asking for a specific constructor that does not exist in the provided Class, you'll get NoSuchMethodException be it a class for an interface, primitive type, array, void or simply a class that does not declare such a constructor.
Above I emphasised the word specific. For example, in a similar method that returns all constructors for a Class (Class::getDeclaredConstructors) interfaces are handled appropriately:
Returns an array of
Constructorobjects reflecting all the constructors declared by the class represented by thisClassobject. These are public, protected, default (package) access, and private constructors. The elements in the array returned are not sorted and are not in any particular order. If the class has a default constructor, it is included in the returned array. This method returns an array of length 0 if thisClassobject represents an interface, a primitive type, an array class, or void.
Answers 3
This is the use case I can think of: on a reflection-based application, a method receives a Class argument. The method needs to construct an instance of the given class, so it checks for the declared constructors. This is a simplified example that just prints the constructors on four different use cases:
- A class instance invoking getClass()
- An interface instance invoking getClass()
- An actual ClassX.class
An actual InterfaceY.class
public class Testctor { public static void main(String[] args) { new Testctor().testGetDeclCtors(); } public void testGetDeclCtors() { Class1 c1 = new Class1(4); printClassInfo(c1.getClass()); I2 i2 = c1; printClassInfo(i2.getClass()); printClassInfo(Class1.class); printClassInfo(I2.class); } private void printClassInfo(Class<?> claz) { Constructor<?> ctor = null; try { ctor = claz.getDeclaredConstructor(); } catch (NoSuchMethodException | SecurityException e) { } System.out.println(claz+": "+ctor); } } interface I2 { } class Class1 implements I2 { public Class1() { } public Class1(int x) { } }
This prints these results:
class test.Class1: public test.Class1() class test.Class1: public test.Class1() class test.Class1: public test.Class1() interface test.I2: null
0 comments:
Post a Comment