Java泛型 - <int>到<integer> </integer> </int>

时间:2011-02-15 06:26:17

标签: java generics primitive-types type-erasure

在学习Java Generics的过程中,我陷入了困境 它写成“ Java Generics仅适用于Objects而非原始类型”。

例如

 Gen<Integer> gen=new Gen<Integer>(88);     // Works Fine ..  

但是,使用int,char等原始类型......

 Gen<int> gen=new Gen<int>(88) ;    // Why this results in compile time error 

我的意思是说,因为java泛型确实有自动装箱&amp;取消装箱功能,那么为什么在我们为类声明特定类型时无法应用此功能?

  

我的意思是,为什么Gen<int>没有   自动转换为   Gen<Integer>

请帮我澄清这个疑问 感谢。

4 个答案:

答案 0 :(得分:9)

Autoboxing并没有说你可以使用int而不是Integer。自动装箱自动化装箱和拆箱过程。例如。如果我需要将一些原始int存储到集合中,我不需要手动创建wrpper对象。 Java编译器一直在关注它。在上面的示例中,您将实例化一个Integer类型的泛型对象。这个泛型对象仍然可以正常使用int,但将int声明为泛型类型是错误的。泛型只允许对象引用而不允许原语。

答案 1 :(得分:3)

正如您所发现的,您不能在Java泛型中将原始类型作为类型参数提及。为什么会这样?在很多地方都会详细讨论,包括Java bug 4487555

答案 2 :(得分:2)

简单的解释:泛型就是这样定义的。

从Java角度来看,这是一个很好的理由:它简化了类型擦除和转换为编译器的字节代码。所有编译器需要做的就是进行一些转换。

对于非基元,编译器必须决定是否要转换或收件箱/发件箱,它需要有额外的验证规则(extends&对基元没有意义,?是否应包含基元,是或否等等?并且必须处理类型转换(假设您使用long对参数进行参数化并添加int ...?)

从程序员的角度来看,这是一个很好的理由:性能不佳的操作仍然可见!允许原始作为类型参数将需要隐藏自动装箱(用于存储的收件箱,用于读取操作的发件箱。收件箱可能会创建昂贵的新对象。如果参数化,人们会期望快速操作具有基元的泛型类,但反之亦然。

答案 3 :(得分:0)

这是一个非常好的问题。

正如您所怀疑的那样,抽象肯定可以扩展到类型参数,并使它们对程序员来说是透明的。实际上,这就是大多数现代JVM语言所做的事情(当然是静态类型的)。例子包括Scala,Ceylon,Kotlin等。

这就是你的例子在Scala中的样子:

val gen: Gen[Int] = new Gen[Int](80)

Int只是一个普通的类,就像其他类一样。没有原始对象的区别。

至于为什么Java人员没有这样做...我实际上并不知道原因,但我认为这样的抽象不适合现有的Java规范而不会使语义过于复杂(或者不会牺牲向后兼容性,这肯定不是一个可行的选择。)