All the examples I look at for reflection show creating a new instance of an unknown implementation, and casting that implementation to it's interface. The issue with this is that now you can't call any new methods (only overrides) on the implementing class, as your object reference variable has the interface type. Here is what I have:
Class c = null;
try {
c = Class.forName("com.path.to.ImplementationType");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
InterfaceType interfaceType = null;
try {
interfaceType = (InterfaceType)c.newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
If I only have a reference to "com.path.to.ImplementationType", and I don't know what that type might be (it is coming from a config file), then how can I use the class name to cast it to ImplementationType? Is this even possible?
This question is related to
java
reflection
If you knew the Class
of ImplementationType
you could create an instance of it. So what you are trying to do is not possible.
I'm not absolutely sure I got your question correctly, but it seems you want something like this:
Class c = null;
try {
c = Class.forName("com.path.to.ImplementationType");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
T interfaceType = null;
try {
interfaceType = (T) c.newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
Where T can be defined in method level or in class level, i.e. <T extends InterfaceType>
As an addendum to akf's answer you could use instanceof checks instead of String equals() calls:
String cname="com.some.vendor.Impl";
try {
Class c=this.getClass().getClassLoader().loadClass(cname);
Object o= c.newInstance();
if(o instanceof Spam) {
Spam spam=(Spam) o;
process(spam);
}
else if(o instanceof Ham) {
Ham ham = (Ham) o;
process(ham);
}
/* etcetera */
}
catch(SecurityException se) {
System.err.printf("Someone trying to game the system?%nOr a rename is in order because this JVM doesn't feel comfortable with: ā%sā", cname);
se.printStackTrace();
}
catch(LinkageError le) {
System.err.printf("Seems like a bad class to this JVM: ā%sā.", cname);
le.printStackTrace();
}
catch(RuntimeException re) {
// runtime exceptions I might have forgotten. Classloaders are wont to produce those.
re.printStackTrace();
}
catch(Exception e) {
e.printStackTrace();
}
Note the liberal hardcoding of some values. Anyways the main points are:
//====Single Class Reference used to retrieve object for fields and initial values. Performance enhancing only====
Class<?> reference = vector.get(0).getClass();
Object obj = reference.newInstance();
Field[] objFields = obj.getClass().getFields();
You want to be able to pass in a Class and get a type-safe instance of that class? Try the following:
public static void main(String [] args) throws Exception {
String s = instanceOf(String.class);
}
public static <T> T instanceOf (Class<T> clazz) throws Exception {
return clazz.newInstance();
}
Source: Stackoverflow.com