原始类型和性能

时间:2015-03-20 13:58:32

标签: java generics

在Effective Java的第140页,我们被告知带有通配符的方法签名优于具有仅出现一次的类型参数的方法签名。例如,

public static void swap(List<?> list, int i, int j)

优于

public static <T> void swap(List<T> list, int i, int j)

但是,无法将List<?>的项目设置为任何内容(null除外),因此有效Java建议编写一个私有帮助程序方法,以使用通配符工作签名。

private static <T> void swapHelper(List<T> list, int i, int j) {
    list.set(i, list.set(j, list.get(i)));
}

public static void swap(List<?> list, int i, int j) {
    swapHelper(list, i, j);
}

但是,我查看了Collections.swap的源代码,发现他们解决List<?>问题的方法是使用原始类型

public static void swap(List<?> list, int i, int j) {
    final List l = list;
    l.set(i, l.set(j, l.get(i)));
}

我们建议不要在新代码中使用原始类型(instanceof检查除外)。那么,我想知道这里的原因是什么?在这里使用原始类型而不是调用私有帮助器方法是否有性能优势?如果没有,是否有任何使用原始类型可以提高性能的例子?

1 个答案:

答案 0 :(得分:6)

过早优化是万恶之源。您很可能会发现JIT编译器会将您的swap方法和swapHelper方法内联,如果它们成为性能瓶颈的话。通常,Java JIT编译器非常适合检测性能瓶颈。

但是,如果您对性能感兴趣,那么为什么不为Collections.swap方法和使用辅助方法的变体编写基准。这将为您提供这个问题的答案。只需确保执行足够多次迭代,JIT编译器将交换函数识别为瓶颈,并通过内联方法调用来优化瓶颈。

我会遵循Effective Java提供的建议而不是Collections.swap中的代码。我想你刚刚发现证据表明程序员有时会走捷径。这并不意味着你应该这样做。