I want to instantiate a class by the value of a String. I found several tutorials that show several methods for doing this. The class MUST inherit from a certain interface
In all essence that is what will happen regardless of whether you're using a third party toolkit for it or not. Casting the object will inherently be mandatory unless expecting an Object
. You can however make a routine which does that for you:
public <T> T instantiateObject(String name, Class<T> cls) throws Exception {
return (T) Class.forName(name).newInstance();
}
Which you can use:
AClass cls = instantiateObject("com.class.AClass", AClass.class);
But if you come this far, the String name
is actually redundant (given AClass is a concrete class). You might as well:
public <T> T instantiateObject(Class<T> cls) throws Exception {
return (T) Class.forName(cls.getCanonicalName()).newInstance();
}
Which you can use:
AClass cls = instantiateObject(AClass.class);
The alternative is to use forName
, but it does not get much better than what you currently have:
ImplementMe a =
(ImplementMe) Class.forName("my.package.IImplementedYou").newInstance();
a.runMe();
Indeed, forName
will use getClassLoader().loadClass()
behind the scenes to load the class, as you can see in the source code of Class.java
.
What you have may work, but you don't have to load the class using the same classloader that loaded ImplementMe. This should work equally well:
Object newInstance = this.getClass().getClassLoader().loadClass("my.package.IImplementedYou").newInstance();
The important thing is that the classloader knows both the class file with the implementation of "my.package.IImplementedYou" and the class with the implementation of "ImplementMe".
You may explicitly check that IImplementedYou really implements ImplementMe like this:
if(newInstance instanceof my.package.IImplementedYou) {
((ImplementMe)newInstance).runMe();
}
You may also check that IImlementedYou really is implementing the interface before creating the instance:
Class c = this.getClass().getClassLoader().loadClass("my.package.IImplementedYou");
if(ImplementMe.class.isAssignableFrom(c)) {
Object newInstance = c.newInstance();
}