Java noob:仅针对对象的generics?
我是Java的新手。 在编写Map 时,我发现声明Map
是一个语法错误,而Map
是正常的。 是否只能在Java中实例化对象类型的generics,而不是原语? 如果是这样,基元的装箱/拆箱会有明显的性能损失吗?
是的,你只能使用参考类型作为generics类型参数,是的,由于装箱/拆箱会有一些性能损失(大部分都可以自动完成)。
以下是Java Generics FAQs的引用:
原始类型是否允许作为类型参数?
不可以。只有引用类型可以用作类型参数。 参数化类型(如
List
或Set
是非法的。 只有引用类型可用于实例化generics类型和方法。 我们必须使用相应的包装器类型作为类型参数来声明List
,而不是List
。[…]注意,缺乏原始类型实例会导致性能损失。 Autoboxing和-unboxing使得generics类型的包装器类型实例在源代码中非常方便和简洁。 但简洁的符号隐藏了这样一个事实,即幕后虚拟机创建并使用了大量的包装器对象,每个对象必须被分配并随后进行垃圾回收。 使用generics类型无法实现直接使用原始类型值的更高性能。 只有常规类型才能提供使用原始类型值的最佳性能。
如果您绝对需要性能, Trove有许多专门用于基本类型的数据结构,但是对于大多数实际用途,使用带有Java Collections Framework类的盒装基元类型应该产生超过可接受的性能。
也可以看看
- Effective Java 2nd Edition,Item 49:将原始类型更喜欢盒装类型
- Java语言指南/ Autoboxing
- Java语言指南/generics
- Java教程/generics
是否只能在Java中实例化对象类型的generics,而不是原语?
正确。
如果是这样,基元的装箱/拆箱会有明显的性能损失吗?
就在这里。
有关详细说明,请参见此处: http : //java.sun.com/j2se/1.5.0/docs/guide/language/autoboxing.html
1)是的,Javagenerics只适用于对象类型。 这是因为它们是如何实现的,这是通过类型擦除 – 本质上,一旦它被编译为字节码所有generics类型都被Object
替换 – 这样做是为了使javagenerics可以在不修改底层JVM /字节码的情况下工作(坏)决定,imo)。
2)是的,会有一些拳击/拆箱惩罚; 我害怕,无法避免。
正如其他人所指出的那样,使用基元的包装类会有性能损失。 即使成本不是很明显,如果你真的需要额外的性能提升,你可以简单地为List类创建一个自定义子类,每个基本类型一个(它们不是很多,所以这不是问题)并简单地覆盖方法在列表中放置和获取值并将它们限制为接受每个基元。 这将导致性能提升并保持通用列表代码的详细程度。