我是泛型的新手,并在文章“参数化类型,例如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)
我知道我在这里对泛型的理解存在差距。有人可以指出我在这里缺少什么吗?
您提到的代码可以编译,因为对象“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 不会导致编译时错误,因为它将用调用方法时的类型。
| 归档时间: |
|
| 查看次数: |
9305 次 |
| 最近记录: |