实例化泛型类型 ArrayList<T>

see*_*r27 5 java generics

我是泛型的新手,并在文章“参数化类型,例如ArrayList<T>,不可实例化 - 我们无法创建它们的实例”中读到过。

完整引用,来自 Java in a Nutshell:

参数化类型,例如ArrayList<T>,不可实例化 - 我们无法创建它们的实例。这是因为<T>只是一个类型参数 - 只是一个真正类型的占位符。只有当我们为类型参数提供一个具体的值时,(例如, ArrayList<String>),类型才完全成形,我们可以创建该类型的对象。

如果我们要使用的类型在编译时未知,这就会带来问题。幸运的是,Java 类型系统能够适应这个概念。它通过具有表示为 的未知类型的显式概念来实现<?>

我知道它不应该是可实例化的,因为具体(实际)类型未知。如果是这样,为什么下面的代码编译没有错误?

public class SampleTest {

    public static <T> List<T> getList(T... elements) {

        List<T> lst = new ArrayList<>(); // shouldn't this line return an error? 

        return lst;
    }
}
Run Code Online (Sandbox Code Playgroud)

我知道我在这里对泛型的理解存在差距。有人可以指出我在这里缺少什么吗?

Sim*_*abo 1

您提到的代码可以编译,因为对象“lst”在调用该方法之前并未实际初始化。由于该方法知道它将获取 T 类型的 var-args 参数,因此它可以在这种情况下进行编译。以下面的示例 Wrapper 类为例:

public class Wrapper<T> {


    public static <T> List<T> getList(T... elements){
        List<T> lst = new ArrayList<>();
        for(T element: elements) {
            lst.add(element);
        }
        return lst;
}
Run Code Online (Sandbox Code Playgroud)

}

此代码可以编译,因为尚未调用该方法。调用该方法时,类型 T 将是我们作为 var-args 参数传递的类型,并且代码编译不会出现问题。让我们在 main 方法中测试一下:

 public static void main( String[] args ){

      System.out.println(Wrapper.getList("Hi", "Hello", "Yo"));

 }
Run Code Online (Sandbox Code Playgroud)

输出是:

[Hi, Hello, Yo]
Run Code Online (Sandbox Code Playgroud)

但是,让我们生成一个编译时错误来查看本文在 main 方法中讨论的内容:

Wrapper<T> myWrap = new Wrapper<>();
Run Code Online (Sandbox Code Playgroud)

我们实际上正在尝试在上面的代码中初始化 Wrapper 类的通用对象,但未知。由于即使我们调用该方法,占位符的值也是未知的,因此会导致编译时错误,而在 getList 方法中创建 T 类型的 List 不会导致编译时错误,因为它将用调用方法时的类型。