简体   繁体   English

Java泛型 - <int> 至 <Integer>

[英]Java Generics - <int> to <Integer>

In the way of learning Java Generics, I got stuck at a point. 在学习Java Generics的过程中,我陷入了困境。
It was written " Java Generics works only with Objects and not the primitive types ". 它写成“ Java Generics仅适用于Objects而不适用于原始类型 ”。

eg 例如

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

But, with the primitive types like int,char etc ... 但是,使用int,char等原始类型...

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

I mean to say, since java generics does have the auto-boxing & unboxing feature, then why this feature cannot be applied when we declare a specific type for our class ? 我的意思是说,因为java泛型确实具有自动装箱和拆箱功能,那么当我们为我们的类声明特定类型时,为什么不能应用此功能呢?

I mean, why Gen<int> doesn't automatically get converted to Gen<Integer> ? 我的意思是,为什么Gen<int>不会自动转换为Gen<Integer>

Please help me clearing this doubt. 请帮我清除这个疑问。
Thanks. 谢谢。

Autoboxing doesn't say that you can use int instead of Integer. Autoboxing并没有说你可以使用int而不是Integer。 Autoboxing automates the process of boxing and unboxing. 自动装箱自动化装箱和拆箱过程。 Eg If I need to store some primitive int to a collection, I don't need to create the wrpper object manually. 例如,如果我需要将一些原始int存储到集合中,我不需要手动创建wrpper对象。 Its been taken care by Java compiler. Java编译器一直在关注它。 In the above example you are instantiating an generic object which is of Integer type. 在上面的示例中,您将实例化一个Integer类型的泛型对象。 This generic object will still work fine with int but declaring int as a generic type is wrong. 这个泛型对象仍然可以正常使用int,但将int声明为泛型类型是错误的。 Generics allow only object references not the primitives. 泛型只允许对象引用而不是基元。

As you have discovered, you can't mention a primitive type as a type parameter in Java generics. 正如您所发现的,您不能在Java泛型中将原始类型作为类型参数提及。 Why is this the case? 为什么会这样? It is discussed at length in many places, including Java bug 4487555 . 它在很多地方都有详细讨论,包括Java bug 4487555

The simple explanation: Generics are defined that way. 简单的解释:泛型是这样定义的。

A good reason from the Java perspective: It simplifies type erasure and translation to byte code for the compiler. 从Java的角度来看,这是一个很好的理由:它简化了类型擦除和转换为编译器的字节代码。 All the compiler needs to do is some casting. 所有编译器需要做的是一些转换。

With non-primitives the compiler would have to decide whether to cast or to inbox/outbox, it would to need to have additional validating rules ( extends and & wouldn't make sense with primitives, should a ? include primitives, yes or no? and so on) and have to handle type conversions (assume you parametize a collection with long and add an int ...?) 随着非原语编译器将不得不决定是否投或收件箱/发件箱,那就需要有额外的验证规则( extends&将没有任何意义与原语,应在?包括原语,是或否?等等)并且必须处理类型转换(假设您使用long参数化一个集合并添加一个int ...?)

A good reason from a programmers perspective: operations with a bad performance are kept visible! 从程序员的角度来看,这是一个很好的理由:性能不佳的操作是可见的! Allowing primitves as Type Arguments would require hidden autoboxing (inboxing for store, outboxing for read operations. Inboxing may create new objects which is expensive. People would expect fast operations if they parametize a generic class with primitives but the opposite would be true. 允许原始作为类型参数将需要隐藏的自动装箱(用于存储的收件箱,用于读取操作的发件箱。收件箱可能会创建昂贵的新对象。如果他们使用基元对泛型类进行参数化,人们会期望快速操作,但情况恰恰相反。

That's a very good question. 这是一个非常好的问题。

As you suspected, the abstraction could surely be extended to the type parameters, and made them trasparent to the programmer. 正如您所怀疑的那样,抽象肯定可以扩展到类型参数,并使它们对程序员来说是透明的。 In fact, that is what most modern JVM languages do (statically typed ones, of course). 实际上,这就是大多数现代JVM语言所做的事情(当然是静态类型的)。 Examples include Scala, Ceylon, Kotlin etc. 例子包括Scala,Ceylon,Kotlin等。

This is what your example would look like in Scala: 这就是您的示例在Scala中的样子:

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

Int is just a regular class, just like other classes. Int只是一个普通的类,就像其他类一样。 There is no primitive-object distinction whatsoever. 没有任何原始对象的区别。

As to why Java people did not do it... I don't actually know the reason, but I imagine such an abstraction would not fit with the existing Java specification without overcomplicating the semantics (or without sacrificing the backward compatibility, which is certainly not a viable option). 至于为什么Java人没有这样做......我实际上并不知道原因,但我认为这样的抽象不适合现有的Java规范而不会过度复杂语义(或者不会牺牲向后兼容性,这当然是肯定的不是一个可行的选择)。

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

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