How to make a reference to a class using a string of the same name
假设我有两个类 Foo 和 Bar,它们实现了接口 A。我要么想制作一个 Foo 或 Bar 的 ArrayList。在命令行参数中,用户必须输入 Foo 或 Bar 中的任意一个,以了解他们正在尝试创建 ArrayList of.
的对象
所以:
1 2 3 4 |
我如何从字符串类型到对类 Foo 或 Bar 的引用,所以它正在执行
1 2 3 | ArrayList<Foo> list = new ArrayList<Foo>(); or ArrayList<Bar> list = new ArrayList<Bar>(); |
这样我可以做到以下几点:
1 2 3 4 | for(int i = 0 ; i < list.size() ; i++){ list(i).doSomething(); //doSomething is a function in interface A that Foo and Bar are required to implement } |
明确地说,我不想要
1 | if (type.equals("Foo")) list = ArrayList<Foo>(); |
我希望能够使用与 type 同名的任何有效类创建一个 ArrayList。
这在 Java 中是不可能的。您可以使用反射检索类型名称,但无法动态创建泛型类型。
原因是泛型类型仅在编译时存在,编译器使用它来强制执行静态类型安全。在运行时,通用信息被丢弃,因此执行您所要求的操作甚至没有意义(在当前的 Java 哲学中)。在运行时,泛型类型已转换为
编译器需要知道类型,听起来您想将类型视为运行时变量而不是编译时事实。
查看在运行时获取类的泛型类型。它本质上问同样的事情,您将获得有关使用反射的可能解决方案的良好信息。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | public class ForNameTest { public static void main(String[] argv) throws ClassNotFoundException, InstantiationException, IllegalAccessException { java.util.ArrayList<String> arrayList = null; try { Class< ? > createdClass = Class.forName("java.util.ArrayList<java.lang.String>"); arrayList = (java.util.ArrayList<String>) (createdClass.newInstance()); arrayList.add("ABC"); System.out.println("First case" + arrayList.toString()); } catch (ClassNotFoundException e) { System.out.println("Exception in first case:" + e.toString()); } try { Class< ? > createdClass = Class.forName("java.util.ArrayList"); arrayList = (java.util.ArrayList<String>) (createdClass.newInstance()); arrayList.add("ABC"); System.out.println("Second case" + arrayList.toString()); } catch (ClassNotFoundException e) { System.out.println("Exception in second case:" + e.toString()); } } } |
输出:
1 2 3 4 5 6 7 8 | C:\\JavaTools>javac ForNameTest.java Note: ForNameTest.java uses unchecked or unsafe operations. Note: Recompile with -Xlint:unchecked for details. C:\\JavaTools>java ForNameTest Exception in first case: java.lang.ClassNotFoundException: java.util.ArrayList<java.lang.S tring> Second case [ABC] |
(不确定这证明了什么——你仍然不能将你的 ArrayList 声明为变量(vs
您可以维护实现该接口的所有可能类型的列表,然后迭代它们的类型,直到找到与输入字符串匹配的类型。除此之外,我认为您在 Java 中会遇到麻烦。
将数组列表声明为
使用
这里有个例子 - "Class.forName()" 和 "Class.forName().newInstance()" 有什么区别?