This question already has an answer here:
Motivation: A friend of mine holds a tutorial at university for the new students and I visited him today. He got an exercise for the class and I did it, the most complicated and worst way possible. However, I stumbled across an unexpected exception on Reflection, when I tried to instance a nested class.
I broke down the classes to get a more simple example (Ignore the fact, that nobody ever would do that):
public class DeepJavaNested {
/**
* A method, that holds an inner class
*/
public void outerClassFoo() {
/**
* Class enclosed by method
*/
class InnerClass {
/**
* Default constructor of InnerClass
*/
public InnerClass() {
System.out.println("Constructed instance of " + getClass().getName());
}
/**
* Just to test the created object
*/
public void foo() {
System.out.println("Successfully invoked a pointless method!");
}
}
}
}
Additionally I have a main method which tries two things. At first, it gets the Reflection class object of the nested class:
Class<?> innerClass = null;
try {
innerClass = Class.forName("deep.nested.DeepJavaNested$1InnerClass");
} catch (ClassNotFoundException e) {
assert false;
}
Then, it tries to invoke the constructor by the two ways, Reflection offers:
try {
// get the (obviously declared) default constructor for the inner class
Constructor<?> innerClassConstructor = innerClass.getConstructor();
// set it accessible, just in case, I am missing something, that would hide it
innerClassConstructor.setAccessible(true);
// invoke the constructor and get an instance of InnerClass
Object instanceOfInnerClass = innerClassConstructor.newInstance();
// invoke test method
innerClass.getMethod("foo").invoke(instanceOfInnerClass);
} catch (NoSuchMethodException e) {
System.err.println("Reflection failed to find constructor: " + e.getMessage());
} catch (IllegalAccessException | InvocationTargetException | InstantiationException e) {
e.printStackTrace();
}
And, because I know, that this does not work; the second way:
try {
// invoke the default constructor using the evil way
Object innerClassObj = innerClass.newInstance();
// invoke test method
innerClass.getMethod("foo").invoke(innerClassObj);
} catch (InstantiationException e) {
System.err.println("Reflection failed to instance class: " + e.getMessage());
} catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
e.printStackTrace();
}
The resulting output of the application:
Reflection failed to find constructor: deep.nested.DeepJavaNested$1InnerClass.<init>()
Reflection failed to instance class: deep.nested.DeepJavaNested$1InnerClass
So obviously, Java cannot find the public constructor and is also unable to create an instance of the class with the messy way, that also expects a default constructor to be available.
My question now: Did I miss something, or is Java Reflection not able to instance classes, that are not enclosed by a class, but by a method?
The whole code example is also available as a Gist: http://ift.tt/2hOs6f3
Aucun commentaire:
Enregistrer un commentaire