Re: Problem: Calling methods of dynamically loaded inner classes at runtime
Thea
Please don't take this as an insult, but you seem to be a little out of your
depth. Reflective programming requires a good understanding of the
fundamentals of Java, which perhaps you are not as strong on yet as you need to
be.
Anyway, I've put together a little working example, which maybe will help you
to sort this stuff out. I'll put it at the end of this message.
Constructor attributeCon = attributeClass.getConstructor();
One potential problem here (and I admit it's a bit obscure -- I had forgotten
all about it until I tried it just now), is that if your nested or inner
classes have a default constructor (you don't define one explicitly) the one
that javac creates for you is not public unless the nested classes are public
themselves. So, if that's the situation, you will have to use
Class.getDeclaredConstructor() instead of Class.getConstructor(), since the
latter only lists public constructors.
Javac always does create a default constructor if none is defined explicitly,
for any kind of class (not just nested), but it takes its access from the
class. If the class is nested /and/ declared private, then javac does
something even more odd and inconvenient -- which I hope you won't need to
worry about; we'll deal with that if we have to.
public Constructor<T> getConstructor(Class... parameterTypes)
it says it should be array of parameters... though I have no idea how
to create it (I mean, what type(s) should I use) I tried several things
but I don't seem to catch the idea...
If you are passing an array then the elements should be the java.lang.Class
objects corresponding to the parameter types. If you know the class in advance
then its easiest to use a "class literal", something like
String.class
which evaluates to the class object for java.lang.String. Since
getConstructor() had been retrofitted to use variadic parameter lists (which
just means that the compiler builds and initialises the array for you from the
parameters you supply when you call it), you can write, for instance:
cl.getConstructor(Class1.class, Class2.class, Integer.class);
rather than having to create an array explicitly.
-- chris
========== Outer.java ============
interface Doable
{
void doit();
}
public class Outer
{
private static String staticField = "(static in class Outer)";
private String instanceName;
Outer(String str)
{
instanceName = str;
}
static class StaticNested
implements Doable
{
public void
doit()
{
System.out.printf("\tdoit called from %s%n", this);
System.out.printf("\tstaticField = %s%n", staticField);
System.out.println();
}
}
class Inner
implements Doable
{
public void
doit()
{
System.out.printf("\tdoit() called from %s%n", this);
System.out.printf("\tstaticField = %s%n", staticField);
System.out.printf("\tinstanceName = %s%n", instanceName);
System.out.println();
}
}
void
example()
throws Throwable // only to keep the example short !!
{
System.out.printf("*** I am %s ***%n", instanceName);
System.out.println("exampleWithoutReflection()");
exampleWithoutReflection();
System.out.println("exampleWithReflection()");
exampleWithReflection();
System.out.println("**** End ***");
}
void
exampleWithoutReflection()
{
new StaticNested().doit();
new Inner().doit();
}
void
exampleWithReflection()
throws Throwable // only to keep the example short !!
{
Class cl;
java.lang.reflect.Constructor ctor;
Doable doable;
// NB: we have to use getDeclaredConstructor()
// instead of getConstructor() since the implicit
// ctors for the nested classes are not public
// static nested class
cl = Class.forName("Outer$StaticNested");
ctor = cl.getDeclaredConstructor();
doable = (Doable)ctor.newInstance();
doable.doit();
// inner class, we have to pass ourself to the ctor
cl = Class.forName("Outer$Inner");
ctor = cl.getDeclaredConstructor(Outer.class);
doable = (Doable)ctor.newInstance(this);
doable.doit();
}
public static void
main(String[] args)
throws Throwable // only to keep the example short !!
{
Outer joan = new Outer("Joan");
Outer fred = new Outer("Fred");
joan.example();
fred.example();
}
}
==========================