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
Here's how I would do it:
ImplementMe noCastNeeded =
this.getClassLoader()
.loadClass("my.package.IImplementedYou")
.asSubclass(ImplementMe.class).newInstance();
There are some Exceptions to catch but that's ok I think. :)
You will need a cast, because the compiler cannot tell from the code that the object is of type ImplementMe. It thus requires the programmer to issue a cast, which will throw a ClassCastException if the object is not an ImplementMe instance.
No, there is no better way (by design). You are not supposed to do this, Java is designed as a type-safe language. However, I can understand that you sometimes need to do things like this, and for that purposes you can create a library function like this:
public <T> T instantiate(final String className, final Class<T> type){
try{
return type.cast(Class.forName(className).newInstance());
} catch(InstantiationException
| IllegalAccessException
| ClassNotFoundException e){
throw new IllegalStateException(e);
}
}
Now your client code can at least call this method without casting:
MyInterface thingy =
instantiate("com.foo.bar.MyInterfaceImpl", MyInterface.class);
You can shorten it a bit like
ImplementMe a = (ImplementMe) Class
.forName("my.package.IImplementedYou")
.newInstance();
but you can't get rid of the cast. There may be a way to avoid the cast, but only if you can avoid the subproblem of loading class by name.
Try Class.forName("my.package.IImplementedYou")
.
(MyInterface)Class.forName(className).newInstance()