如何初始化作为参数接收的 class 类型的列表?

How to initialize a list of a class type received as a parameter?

我是 Java 的初学者。

如何初始化作为参数接收的 class 类型的列表?我有一个方法将 Class<?> 参数作为参数,我想创建一个 class 类型的列表。

public List<?> returnList(Class<?> listItemType) {
    //create a list of type "listItemType"
    //populate the list
    //return the list
}

我试过

List<listItemType> list = new ArrayList<listItemType>()

但 VSCode 显示 listItemType cannot be resolved to a type

我也试过<? extends listItemType><listItemType.getName()>和下面的代码,但它们似乎也不起作用。

Object obj = listItemType.getDeclaredConstructor().newInstance();
List<obj.getClass()> = new ArrayList<obj.getClass()>();

你需要的是 generic method.

Generic methods allow type parameters to be used to express dependencies among the types of one or more arguments to a method and/or its return type.

这是一个完整的例子:

public class NewMain {

    private static class Foo {

        public Foo() {
        }
    }
    
    public static void main(String[] args) {
        // TODO code application logic here
        List<Foo> foos = returnList(Foo.class);
        System.out.println(foos.get(0));
    }
    
    public static <T> List<T> returnList(Class<T> listItemType) {
        List<T> list = new ArrayList<>();
        try {
            T obj = listItemType.getConstructor().newInstance();
            list.add(obj);
        } catch (Exception ex) {
            Logger.getLogger(NewMain.class.getName()).log(Level.SEVERE, null, ex);
        }
        return list;
    }
    
}

如果您使该方法成为具有命名类型参数的泛型方法,它将起作用。例如:

public <T> List<T> returnList(Class<T> listItemType) {
    List<T> list = new ArrayList<>();
    try {
        list.add(listItemType.getConstructor().newInstance());
    } catch (ReflectiveOperationException ex) {
        // do something
    }
    return list;
}

请注意,可能存在各种例外情况。例如,class 可能没有合适的构造函数,构造函数可能无法访问,或者它可能会抛出异常。此方法的完整版本应该做一些适当的事情,或者声明相关的异常,以便它们可以传播给调用者和其他人。

如果没有 named 类型参数 T,您不会将 List<?> 中的通配符连接到 Class<?> 中的通配符。所以编译器不会知道 returnList(Foobar.class) 的目的是 return a List<Foobar>.

并且无法像 List<listItemType> 中那样将变量名称 listItemType 用作 class 名称。这就是为什么您得到“listItemType 无法解析为类型”的原因。变量名称和类型名称位于不同的 Java 命名空间中。

您的尝试 <? extends listItemType> 因同样的原因而失败,并且 <listItemType.getName()> 失败,因为表达式不是类型。

考虑这些失败尝试的另一种方式是它们使用运行时值(例如 listItemType 的值)进行编译时类型检查。这意味着编译器需要能够展望未来,以了解运行时值 是什么。千里眼不是当前一代 Java 编译器的功能:-)。