原始类型和性能

Raw types and performance

在 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 除外),因此 Effective 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 检查除外)。那么,我想知道这里的原因是什么?在这里使用原始类型而不是调用私有辅助方法是否有性能优势?如果没有,是否有使用原始类型可以提高性能的示例?

过早的优化是万恶之源。您很可能会发现 JIT 编译器会内联您的交换方法和 swapHelper 方法(如果它们最终成为性能瓶颈)。一般来说,Java JIT 编译器在检测性能瓶颈方面非常好。

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

我会遵循 Effective Java 给出的建议,而不是 Collections.swap 中的代码。我认为您只是发现了程序员有时会走捷径的证据。这并不意味着您应该做同样的事情。