在学习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>
?
请帮我澄清这个疑问 感谢。
答案 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规范而不会使语义过于复杂(或者不会牺牲向后兼容性,这肯定不是一个可行的选择。)