【问题标题】:Can I use generics over reference types only?我可以只使用泛型而不是引用类型吗?
【发布时间】:2010-06-10 15:14:04
【问题描述】:

在编写地图时,我发现声明Map<int, int> 是语法错误,而Map<Integer, Integer> 是可以的。

是否只能在 Java 中实例化对象类型上的泛型,而不是原始类型?如果是这样,对基元的装箱/拆箱是否有明显的性能损失?

【问题讨论】:

  • 正如其他人指出的那样,存在一定的性能损失。但是,性能分析工具的显着性和用户的显着性之间存在很大差异。

标签: java generics


【解决方案1】:

是的,您只能对泛型类型参数使用引用类型,是的,由于装箱/拆箱(大部分情况下可以自动完成)会导致一些性能损失。

这是Java Generics FAQs的引述:

是否允许原始类型作为类型参数?

没有。只有引用类型可以用作类型参数。 List<int>Set<short> 等参数化类型是非法的。只有引用类型可以用于泛型类型和方法的实例化。我们必须声明 List<Integer>,而不是 List<int>,使用相应的包装类型作为类型参数。

[...] 请注意,缺少原始类型实例会导致性能损失。自动装箱和拆箱使得在源代码中使用泛型类型的包装类型实例非常方便和简洁。但是简洁的符号隐藏了这样一个事实,即虚拟机在幕后创建并使用了许多包装器对象,每个包装器对象都必须被分配并随后被垃圾收集。使用泛型类型无法实现直接使用原始类型值的更高性能。只有常规类型才能提供使用原始类型值的最佳性能。

如果您绝对需要性能,Trove 有许多专门用于原始类型的数据结构,但对于大多数实际用途,使用带有 Java 集合框架类的装箱原始类型应该会产生超出可接受的性能。

另见

【讨论】:

    【解决方案2】:

    是否只能在 Java 中 在对象上实例化泛型 类型,而不是基元?

    正确。

    如果有,是否有明显的 性能损失 基元的装箱/拆箱?

    是的,有。

    详细说明请看这里:http://java.sun.com/j2se/1.5.0/docs/guide/language/autoboxing.html

    【讨论】:

      【解决方案3】:

      1) 是的,Java 泛型仅适用于对象类型。这是因为它们是如何实现的,即通过type erasure - 本质上,一旦它被编译为字节码,所有泛型类型都将替换为Object - 这样做是为了让java泛型可以在不修改底层JVM/的情况下工作字节码(错误的决定,imo)。

      2) 是的,会有一些装箱/拆箱处罚;无法避免,我害怕。

      【讨论】:

        【解决方案4】:

        正如其他人所指出的那样,对原语使用包装类会降低性能。即使成本不是很明显,如果您真的需要额外的性能提升,您可以简单地为 List 类创建自定义子类,每个原始类型一个(它们并不多,所以这不是问题)并简单地覆盖方法在列表中放置和获取值并将它们限制为接受每个原语。这将提高性能并保持通用列表代码的详细程度。

        【讨论】:

        • 实现List 本身不会带来任何的性能提升,因为公共接口仍然需要装箱。你需要重载(而不是override)所有方法,如果你这样做了,那么为什么要首先实现List
        • 我想到的是子类化一个具体的列表实现,例如 LinkedList。您可以继承 LinkedList> 并提供“包装”方法来添加和检索整数而不是整数,例如...
        猜你喜欢
        • 1970-01-01
        • 2021-10-09
        • 2010-10-22
        • 1970-01-01
        • 1970-01-01
        • 2012-12-09
        • 1970-01-01
        • 1970-01-01
        • 2011-03-22
        相关资源
        最近更新 更多