提问人:Saurabh Gokhale 提问时间:4/27/2010 最后编辑:MichaelSaurabh Gokhale 更新时间:6/4/2020 访问量:103729
为什么 Java 泛型不支持基元类型?
Why don't Java Generics support primitive types?
问:
为什么 Java 中的泛型可以处理类,而不能处理基元类型?
例如,这工作正常:
List<Integer> foo = new ArrayList<Integer>();
但这是不允许的:
List<int> bar = new ArrayList<int>();
答:
Java 中的泛型是一个完全编译时的构造 - 编译器将所有泛型用法转换为正确的类型。这是为了保持与以前的 JVM 运行时的向后兼容性。
这:
List<ClassA> list = new ArrayList<ClassA>();
list.add(new ClassA());
ClassA a = list.get(0);
变成(大致):
List list = new ArrayList();
list.add(new ClassA());
ClassA a = (ClassA)list.get(0);
因此,用作泛型的任何内容都必须可转换为 Object(在此示例中返回 ),而基元类型则不能。所以它们不能用于泛型。get(0)
Object
评论
在 Java 中,泛型的工作方式是......至少部分......因为它们是在语言设计多年后才被添加到语言中的1.语言设计者在泛型选项上受到限制,因为他们必须提出一个与现有语言和 Java 类库向后兼容的设计。
其他编程语言(例如 C++、C#、Ada)确实允许将基元类型用作泛型的参数类型。但这样做的另一面是,此类语言的泛型(或模板类型)实现通常需要为每个类型参数化生成泛型类型的不同副本。
1 - 泛型未包含在 Java 1.0 中的原因是时间压力。他们认为他们必须尽快发布 Java 语言,以填补 Web 浏览器带来的新市场机会。詹姆斯·高斯林(James Gosling)表示,如果他们有时间,他希望将仿制药包括在内。如果发生这种情况,Java 语言会是什么样子是任何人的猜测。
这些集合被定义为需要一个派生自 的类型。基类型根本不这样做。java.lang.Object
评论
根据 Java 文档,泛型类型变量只能使用引用类型实例化,而不能使用基元类型实例化。
这应该出现在 Java 10 的 Project Valhalla 下。
在 Brian Goetz 关于专业化现状的论文中
关于原语不支持泛型的原因,有一个很好的解释。以及,它将如何在 Java 的未来版本中实现。
Java 当前的擦除实现,它为所有引用实例化生成一个类,不支持原始实例化。(这是一个同构转换,Java 的泛型只能涵盖引用类型的限制来自同构转换对 JVM 字节码集的限制,它使用不同的字节码对引用类型和基元类型的操作。但是,Java 中擦除的泛型同时提供了行为参数(泛型方法)和数据参数(泛型类型的原始实例化和通配符实例化)。
...
选择了一种同构转换策略,其中泛型类型变量在合并到字节码中时被擦除到其边界。这意味着,无论一个类是否是泛型类,它仍然编译为具有相同名称且成员签名相同的单个类。类型安全性在编译时得到验证,运行时不受泛型类型系统的限制。反过来,这施加了泛型只能对引用类型起作用的限制,因为 Object 是最通用的可用类型,并且它不会扩展到基元类型。
在 Java 中,泛型是通过使用“类型擦除”实现的,以实现向后兼容性。 所有泛型类型在运行时都转换为 Object。 例如
public class Container<T> {
private T data;
public T getData() {
return data;
}
}
将在运行时显示为,
public class Container {
private Object data;
public Object getData() {
return data;
}
}
编译器负责提供适当的强制转换以确保类型安全。
Container<Integer> val = new Container<Integer>();
Integer data = val.getData()
将成为
Container val = new Container();
Integer data = (Integer) val.getData()
现在的问题是,为什么在运行时选择“Object”作为类型?
答案是 Object 是所有对象的超类,可以表示任何 用户定义的对象。
由于所有基元都不是从“Object”继承的,因此我们不能使用它 作为泛型类型。
仅供参考:瓦尔哈拉项目正试图解决上述问题。
评论