简体   繁体   English

为什么 Java 泛型不支持原始类型?

[英]Why don't Java Generics support primitive types?

Why do generics in Java work with classes but not with primitive types?为什么 Java 中的泛型适用于类而不适用于原始类型?

For example, this works fine:例如,这工作正常:

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

but this is not allowed:但这是不允许的:

List<int> bar = new ArrayList<int>();

Generics in Java are an entirely compile-time construct - the compiler turns all generic uses into casts to the right type. Java 中的泛型完全是编译时构造 - 编译器将所有泛型用途转换为正确类型的强制转换。 This is to maintain backwards compatibility with previous JVM runtimes.这是为了保持与以前的 JVM 运行时的向后兼容性。

This:这个:

List<ClassA> list = new ArrayList<ClassA>();
list.add(new ClassA());
ClassA a = list.get(0);

gets turned into (roughly):变成(大致):

List list = new ArrayList();
list.add(new ClassA());
ClassA a = (ClassA)list.get(0);

So, anything that is used as generics has to be convertable to Object (in this example get(0) returns an Object ), and the primitive types aren't.因此,任何用作泛型的东西都必须可以转换为 Object(在本例中get(0)返回一个Object ),而原始类型则不然。 So they can't be used in generics.所以它们不能用于泛型。

In Java, generics work the way that they do ... at least in part ... because they were added to the language a number of years after the language was designed 1 .在 Java 中,泛型的工作方式与它们相同……至少部分是因为它们是在语言设计1几年后添加到语言中的。 The language designers were constrained in their options for generics by having to come up with a design that was backwards compatible with the existing language and the Java class library .语言设计者在选择泛型方面受到限制,因为他们不得不提出一种向后兼容现有语言和 Java 类库的设计

Other programming languages (eg C++, C#, Ada) do allow primitive types to be used as parameter types for generics.其他编程语言(例如 C++、C#、Ada)确实允许将原始类型用作泛型的参数类型。 But the flip side of doing this is that such languages' implementations of generics (or template types) typically entail generation of a distinct copy of the generic type for each type parameterization.但这样做的另一面是,此类语言对泛型(或模板类型)的实现通常需要为每个类型参数化生成一个不同的泛型类型副本。


1 - The reason generics were not included in Java 1.0 was because of time pressure. 1 - Java 1.0 中未包含泛型的原因是时间压力。 They felt that they had to get the Java language released quickly to fill the new market opportunity presented by web browsers.他们觉得必须尽快发布 Java 语言,以填补 Web 浏览器带来的新市场机会。 James Gosling has stated that he would have liked to include generics if they had had the time. James Gosling 曾表示,如果他们有时间,他会希望包括泛型。 What the Java language would have looked like if this had happened is anyone's guess.如果发生这种情况,Java 语言会是什么样子是任何人的猜测。

In java generics are implemented by using "Type erasure" for backward compatibility.在 Java 中,泛型是通过使用“类型擦除”来实现向后兼容的。 All generic types are converted to Object at runtime.所有泛型类型都在运行时转换为 Object。 for example,例如,

public class Container<T> {

    private T data;

    public T getData() {
        return data;
    }
}

will be seen at runtime as,将在运行时被视为,

public class Container {

    private Object data;

    public Object getData() {
        return data;
    }
}

compiler is responsible to provide proper cast to ensure type safety.编译器负责提供正确的类型转换以确保类型安全。

Container<Integer> val = new Container<Integer>();
Integer data = val.getData()

will become会变成

Container val = new Container();
Integer data = (Integer) val.getData()

Now the question is why "Object" is chose as type at runtime?现在的问题是为什么在运行时选择“对象”作为类型?

Answer is Object is superclass of all objects and can represent any user defined object.答案是Object是所有对象的超类,可以代表任何用户定义的对象。

Since all primitives doesn't inherit from " Object " so we can't use it as a generic type.由于所有原语都不是从“ Object ”继承的,因此我们不能将其用作泛型类型。

FYI : Project Valhalla is trying to address above issue.仅供参考:瓦尔哈拉计划正试图解决上述问题。

As per Java Documentation , generic type variables can only be instantiated with reference types, not primitive types.根据Java 文档,泛型类型变量只能用引用类型实例化,不能用原始类型实例化。

This is supposed to come in Java 10 under Project Valhalla .这应该在Project Valhalla下的 Java 10 中出现。

In Brian Goetz paper on State of the SpecializationBrian Goetz关于专业化状态的论文中

There is an excellent explanation about the reason for which generic were not supported for primitive.关于基元不支持泛型的原因有一个很好的解释 And, how it will be implemented in future releases of Java.并且, 它将如何在 Java 的未来版本中实现

Java's current erased implementation which produces one class for all reference instantiations and no support for primitive instantiations. Java 的当前擦除实现为所有引用实例化生成一个类,并且不支持原始实例化。 (This is a homogeneous translation, and the restriction that Java's generics can only range over reference types comes from the limitations of homogeneous translation with respect to the bytecode set of the JVM, which uses different bytecodes for operations on reference types vs primitive types.) However, erased generics in Java provide both behavioral parametricity (generic methods) and data parametricity (raw and wildcard instantiations of generic types.) (这是同构转换,Java 泛型只能覆盖引用类型的限制来自同构转换对 JVM 字节码集的限制,JVM 对引用类型和原始类型的操作使用不同的字节码。)然而,Java 中的擦除泛型提供了行为参数(泛型方法)和数据参数(泛型类型的原始和通配符实例化)。

... ...

a homogeneous translation strategy was chosen, where generic type variables are erased to their bounds as they are incorporated into bytecode.选择了同构翻译策略,其中泛型类型变量在它们被合并到字节码中时被擦除到它们的边界。 This means that whether a class is generic or not, it still compiles to a single class, with the same name, and whose member signatures are the same.这意味着无论一个类是否是泛型的,它仍然会编译为一个具有相同名称且成员签名相同的类。 Type safety is verified at compile time, and runtime is unfettered by the generic type system.类型安全在编译时验证,运行时不受泛型类型系统的约束。 In turn, this imposed the restriction that generics could only work over reference types, since Object is the most general type available, and it does not extend to primitive types.反过来,这强加了泛型只能在引用类型上工作的限制,因为 Object 是最通用的可用类型,并且它不能扩展到原始类型。

The collections are defined to require a type which derives from java.lang.Object .集合被定义为需要从java.lang.Object派生的类型。 The basetypes simply don't do that.基本类型根本不这样做。

Why do generics in Java work with classes but not with primitive types?为什么Java中的泛型只能用于类,而不能用于原始类型?

For example, this works fine:例如,这可以正常工作:

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

but this is not allowed:但这是不允许的:

List<int> bar = new ArrayList<int>();

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM