MMTTMM
需要一些背景来充分理解这背后的主要原因。基元与类Java中的原始变量包含值(整数,双精度浮点二进制数等)。因为这些值可能具有不同的长度,所以包含它们的变量也可能具有不同的长度(考虑float对比double)。另一方面,类变量包含对实例的引用。引用通常在许多语言中实现为指针(或与指针非常相似的东西)。这些东西通常具有相同的大小,而不管它们指的是(实例的大小Object,String,Integer,等)。类变量的这个属性使它们包含的引用可以互换(在一定程度上)。这允许我们做我们称之为替换的东西:广义上讲,使用特定类型的实例作为另一个相关类型的实例(例如,使用a String作为Object)。原始变量不能以相同的方式互换,也不能彼此互换,也不能互换Object。最明显的原因(但不是唯一的原因)是它们的尺寸差异。这使得原始类型在这方面不方便,但我们仍然需要它们的语言(原因主要归结为性能)。泛型和类型擦除通用类型是具有一个或多个类型参数的类型(确切的数字称为通用arity)。例如,泛型类型定义 List有一个类型参数T,可以是Object(生成具体类型 List),String(List),Integer(List)等等。通用类型比非通用类型复杂得多。当它们被引入Java(在其初始版本之后)时,为了避免对JVM进行根本性更改并可能破坏与旧二进制文件的兼容性,Java的创建者决定以最少侵入性的方式实现泛型类型:所有具体类型的List实际上,编译为(二进制等价物)List(对于其他类型,绑定可能不是Object,但你明白了)。通用arity和类型参数信息在此过程中丢失,这就是我们称之为类型擦除的原因。把两者放在一起现在问题是上述现实的结合:如果在所有情况下都List变为现实List,那么T必须始终是可以直接分配的类型Object。其他任何东西都不允许。因为,正如我们之前所说int,float并且double不能互换Object,所以不能有List,List或者List(除非在JVM中存在明显更复杂的泛型实现)。但是Java提供类型,如Integer,Float和Double其包装类情况下,这些原语,使他们有效地作为替代Object,从而使泛型类型来间接地与原语的工作,以及(因为你可以有List,List,List等)。创建的过程Integer,从一个int,一个Float从float等,被称为拳击。反向称为拆箱。因为每次你想要使用它们时都必须使用原始文件Object,因此有些语言会自动执行此操作 - 这称为自动装箱。