Is there any possible way to pass a class name/path as String argument to call it in code in runtime? Im working with some legacy code and i have no way to change it globally. Creating new integration to it suggest me to create new copy of class X, rename it, and pass new instance of Y i have created manually. My mind tells me to pass Y as some kind of argument and never copy X again.
CodePudding user response:
I don't quite understand why you (think that) you need to do what you are trying to do (why copy class in the first place rather than just using it? why pass classname around instead of the class itself?), but, yeah, you can instantiate classes by (fully qualified) name using reflection.
First you get a handle to the class itself:
val clazz = Class.forName("foo.bar.X")
Then, if constructor does not need any arguments, you can just do
val instance = clazz.newInstance
If you need to pass arguments to constructor, it gets a bit more complicated.
val constructor = clazz.getConstructors().find { c =>
c.getParameters().map(_.getParameterizedType) == args.map(_.getClass)
}.getOrElse (throw new Exception("No suitable constructor found")
// or if you know for sure there will be only one constructor,
// could just do clazz.getConnstructors.headOption.getOrElse(...)
val instance = constructor.newInstance(args)
Note though, that the resulting instance
is of type Object
(AnyRef
), so there isn't much you can actually do with it without casting to some interface type your class is known to implement.
Let me just say it again: it is very likely not the best way to achieve what you are actually trying to do. If you open another question and describe your actual problem (not the solution to it you are trying to implement), you might get more helpful answers.