Java 泛型 - <int> 到 <Integer>

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5000521/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 09:00:08  来源:igfitidea点击:

Java Generics - <int> to <Integer>

javagenericsprimitive-typestype-erasure

提问by sgokhales

In the way of learning Java Generics, I got stuck at a point.
It was written "Java Generics works only with Objects and not the primitive types".

在学习 Java 泛型的过程中,我陷入了困境。
它被写成“ Java 泛型仅适用于对象,而不适用于原始类型”。

e.g

例如

 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.

请帮我清除这个疑问。
谢谢。

采纳答案by mittalpraveen

Autoboxing doesn't say that you can use int instead of Integer. Autoboxing automates the process of boxing and unboxing. E.g. If I need to store some primitive int to a collection, I don't need to create the wrpper object manually. Its been taken care by Java compiler. In the above example you are instantiating an generic object which is of Integer type. This generic object will still work fine with int but declaring int as a generic type is wrong. Generics allow only object references not the primitives.

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

回答by sjr

As you have discovered, you can't mention a primitive type as a type parameter in Java generics. Why is this the case? It is discussed at length in many places, including Java bug 4487555.

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

回答by Andreas Dolk

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. All the compiler needs to do is some casting.

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

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 (extendsand &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 longand 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 hiddenautoboxing (inboxing for store, outboxing for read operations. Inboxing may create new objects which is expensive. People would expect fastoperations if they parametize a generic class with primitives but the opposite would be true.

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

回答by missingfaktor

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). Examples include Scala, Ceylon, Kotlin etc.

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

This is what your example would look like in Scala:

这就是您的示例在 Scala 中的样子:

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

Intis just a regular class, just like other classes. There is no primitive-object distinction whatsoever.

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

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 规范,而不会使语义过于复杂(或者不牺牲向后兼容性,这肯定是不是一个可行的选择)。