繁体   English   中英

如何使用相同名称的字符串引用类

[英]How to make a reference to a class using a string of the same name

假设我有两个实现接口A的类Foo和Bar。我想要创建一个Foo或Bar的ArrayList。 在命令行参数中,用户必须输入Foo或Bar,以确定他们尝试创建ArrayList的对象。

所以:

public static void main(String [] args){
    String type = args[0];
    ArrayList<type> list = new ArrayList<type>();
    }

如何从字符串类型转到类Foo或Bar的引用,以便它正在执行

ArrayList<Foo> list = new ArrayList<Foo>();
or
ArrayList<Bar> list = new ArrayList<Bar>();

这样我可以做到以下几点:

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
}    

要清楚,我不想要类似的东西

if (type.equals("Foo")) list = ArrayList<Foo>();

我希望能够使用与类型相同的任何有效类创建一个ArrayList。

编译器需要知道类型,听起来你想将类型视为运行时变量而不是编译时事实。

检查在运行时获取泛型类 它本质上要求相同的东西,你将获得有关使用反射的可能的解决方案解决方案的良好信息。

这在Java中是不可能的。 您可以使用反射检索类型名称,但无法动态创建泛型类型。

原因是泛型类型仅在编译时存在,并且编译器使用它来强制执行静态类型安全性。 在运行时,通用信息被丢弃,因此在您所要求的内容中(在当前的Java哲学中)甚至没有意义。 在运行时,泛型类型已转换为Object ,编译器在必要时具有替换的类型安全转换。

使用Class.forName(String classNameWithPath)方法 - 它会做你想要的。

这里有一个例子 - “Class.forName()”和“Class.forName()。newInstance()”之间有什么区别?

将数组列表声明为ArrayList<A> 这样它就可以存储Foo和Bar对象,因为它们都实现了接口A.

您可以维护实现该接口的所有可能类型的列表,然后迭代它们的类型,直到找到与输入字符串匹配的类型。 除此之外,我认为你在Java中做这件事会遇到麻烦。

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());
    }
}
}

输出:

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 <?> )类型。但它是,FWIW。)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM