Java泛型 - <int> 转换为 <Integer>

18

在学习Java泛型的过程中,我遇到了一个难点。
文字上写着:“Java泛型只能使用对象,而不能使用基本类型”。

例如:

 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泛型有自动装箱和拆箱功能,那么为什么在声明类的特定类型时不能应用此功能?

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

请帮我解决这个疑惑。
谢谢。


1
可能是泛型语法:类与原始数据类型的重复问题。 - user180100
如果你真的需要使用基本类型,那就使用Trove。 - st0le
4个回答

10

自动装箱并不表示您可以使用 int 替代 Integer。 自动装箱自动化了装箱和拆箱的过程。例如,如果我需要将一些原始int存储到集合中,我不需要手动创建包装对象。这已经被Java编译器处理了。在上面的示例中,您正在实例化一个通用对象,该对象是Integer类型。此通用对象仍将与int正常工作,但将int声明为通用类型是错误的。泛型仅允许对象引用而不是基本类型。


4
如果我没记错的话,这实际上是由编译器处理的,而不是JVM。 - Alain Pannetier
1
@Alain Pannetier - 确实如此,但这并不是争论的重点。(我已经点赞了你的评论!) - user183037

3

正如你所发现的那样,在Java泛型中无法将原始类型作为类型参数进行提及。为什么会这样呢?这在许多地方都有详细讨论,包括Java bug 4487555


1
Java的缺陷数据库又回来了! 好耶。 - Stephen C
1
我应该认真设置的,哈哈。 - sjr
链接已失效 =[ - Troyseph

2
简单解释:泛型被定义为这样。
从Java的角度来看,一个好的理由是:它简化了类型擦除和编译器对字节码的转换。编译器只需要一些强制转换。
对于非基本类型,编译器需要决定是进行强制转换还是装箱/拆箱,并且需要有额外的验证规则(例如,扩展和&符号在基本类型中没有意义,如果将?包含基本类型,则是或否?等等),并且必须处理类型转换(假设您使用long参数化集合并添加int...?)
从程序员的角度来看,一个好的理由是:性能差的操作保持可见!允许基元作为类型参数会要求隐藏自动装箱(存储时的收纳,读取操作的出箱)。收纳可能会创建新对象,这是昂贵的。如果使用基元参数化泛型类,人们希望快速操作,但相反的情况将成为真实情况。

0

这是一个非常好的问题。

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

这就是你在Scala中的示例:

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

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

至于为什么 Java 开发者没有这样做... 我实际上不知道原因,但我想这样的抽象可能不适合现有的 Java 规范,会使语义过于复杂(或者没有牺牲向后兼容性这个可行选项)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接