我有一个Java问题。我有一个配置文件,我读取并提取一些java类的路径,让我们说一个字符串的ArrayList(为方便起见,我将其称为 path2libs )。
我想通过迭代这个' path2libs '数组来动态地为每个类创建一个实例。我试过这样的事情:
Class clazz = Class.forName("test.Demo");
Demo demo = (Demo) clazz.newInstance();
但我不知道我会读什么课,所以我不能做适当的演员。
完成后,我想在每个对象上调用一个方法(在每种情况下都是相同的方法)。所有这些对象都基于一个接口,所以我知道它们的方法。
所以,基本上(总结一下)我有两个问题:)
答案 0 :(得分:2)
有很多问题。
首先,Class#newInstance()
期望相应的类具有带有空参数列表的public
构造函数。因此,您必须确保您要使用的所有类都具有该类。否则,您需要获得适当的Constructor
,使其可访问,并提供适当的参数。
其次,你知道运行时所有类共享的界面吗?如果这样做,您可以将所有实例强制转换为该接口类型
InterfaceType interfaceInstance = (InterfaceType) clazz.newInstance();
interfaceInstance.interfaceMethod(/* arguments */);
如果你不这样做,你将不得不再次依靠反思。
您需要为相应的方法检索Method
,并在方法的参数列表中提供每个参数的类型。
Method method = clazz.getDeclaredMethod("methodName" /*, possible parameter list types */);
然后,您可以在类的实例上调用该方法,再次提供适当的参数。
method.invoke(interfaceInstance /*, possible arguments */);
答案 1 :(得分:2)
“类无法转换为MyInterface”
这听起来像是在尝试将Class
投射到这样的MyInterface
后得到的编译器错误:
MyInterface mi = (MyInterface)Class.forName("test.Demo");
这是无效的,MyInterface不是Class,所以编译器可以确定转换永远不合法。相反,您应该将新实例强制转换为MyInterface。现在,有一种方法可以以更安全的方式执行此操作:
Class<?> wildCls = Class.forName("test.Demo");
Class<? extends MyInterface> miSubtypeCls = (
wildCls.asSubclass(MyInterface.class)
);
MyInterface miSubtype = miSubtypeCls.newInstance();
这类似于非通用版本:
Class rawCls = Class.forName("test.Demo");
MyInterface miSubtype = (MyInterface)rawCls.newInstance();
但是,第一个版本不使用原始类型(不推荐使用),而asSubclass
会在test.Demo
未实现MyInterface
时抛出ClassCastException。为此类场景提供了方法asSubclass
。
这是一个简短的演示:
package test;
public class HelloAsSubclass
implements Runnable {
@Override
public void run() {
System.out.println("hello from Runnable implementation!");
}
public static void main(String[] args) {
try {
Class<?> wildCls = Class.forName("test.HelloAsSubclass");
Class<? extends Runnable> rSubtypeCls = (
wildCls.asSubclass(Runnable.class)
);
Runnable r = rSubtypeCls.newInstance();
r.run();
} catch(
ClassNotFoundException |
InstantiationException |
IllegalAccessException ex
) {
ex.printStackTrace();
}
}
}
当然也要确保你的子类型有一个公共的无参数构造函数(或者没有上面例子中的构造函数,并且基本上是相同的东西),这是newInstance
的要求。否则,您需要将它们by getting a Constructor对象实例化。
答案 2 :(得分:0)
你做得很对。只是,您不会转换为Demo
,而是转换为公共接口。毕竟,您希望对所有这些实例执行 common 。你想调用它们的方法。不知何故,你必须知道这些方法实际上是可用的。这就是接口的用途。