为什么Java泛型不支持基本类型?

为什么Java中的泛型只能与类一起工作,而不能与基本类型一起工作?

例如,这很好:

List<Integer> foo = new ArrayList<Integer>();

但这是不允许的:

List<int> bar = new ArrayList<int>();
97625 次浏览

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中,泛型的工作方式是…至少在某种程度上……因为它们是在语言被设计出来很多年之后才被添加到语言中的。语言设计者在他们的泛型选项中受到了限制的限制,他们必须想出一个与现有语言和Java类库向后兼容的设计。

其他编程语言(如c++、c#、Ada)允许将基元类型用作泛型的参数类型。但这样做的另一面是,此类语言的泛型(或模板类型)实现通常需要为每个类型参数化生成一个不同的泛型类型副本。


1 - Java 1.0中没有包含泛型的原因是时间压力。他们觉得必须尽快发布Java语言,以填补web浏览器带来的新市场机会。詹姆斯·高斯林(James Gosling)曾表示,如果有时间的话,他会想要加入仿制药。如果发生这种情况,Java语言将会是什么样子,这是任何人的猜测。

集合被定义为需要派生自java.lang.Object的类型。基类型不会这样做。

根据Java文档,泛型类型变量只能用引用类型实例化,不能用基元类型实例化。

这应该是在Java 10的项目瓦尔哈拉殿堂下。

Brian Goetz论文专业化的状态

关于原语不支持泛型的原因有优秀的解释。并且,它将如何实施在未来的Java版本中。

Java当前的擦除实现,它为所有引用实例化生成一个类,不支持原语实例化。(这是一种同构转换,Java的泛型只能覆盖引用类型的限制来自于JVM的字节码集的同构转换的限制,JVM使用不同的字节码对引用类型和基本类型进行操作。)然而,Java中的擦除泛型同时提供了行为参数化(泛型方法)和数据参数化(泛型类型的原始和通配符实例化)。

...

我们选择了同构转换策略,在将泛型类型变量合并到字节码中时,将它们擦除到边界。这意味着无论类是否泛型,它仍然编译为单个类,具有相同的名称,并且其成员签名是相同的。类型安全在编译时验证,运行时不受泛型类型系统的限制。反过来,这强加了泛型只能在引用类型上工作的限制,因为Object是可用的最通用的类型,并且它不能扩展到基本类型。

在java中,泛型是通过使用“类型擦除”实现向后兼容性的。 所有泛型类型都在运行时转换为Object。 例如,< / p >
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()

现在的问题是为什么在运行时选择“对象”作为类型?

对象是所有对象的超类,可以表示任何对象

因为所有原语都不继承自"对象",所以我们不能使用它 作为泛型类型。

供你参考:瓦尔哈拉计划正试图解决上述问题。