我在网上遇到过这样的代码和评论 java.util.ImmutableCollections 类:
static final class List0<E> extends AbstractImmutableList<E> {
...
@Override
public E get(int index) {
Objects.checkIndex(index, 0); // always throws IndexOutOfBoundsException
return null; // but the compiler doesn't know this
}
...
}
为什么不呢 throw new IndexOutOfBoundsException(...)?什么原因?
也许,它只是避免代码重复,因为否则它会是这样的:
new IndexOutOfBoundsException(outOfBoundsMessage(..., ...))
但 outOfBounds* 方法是 private,所以按照设计,有人应该调用包装器 return Preconditions.checkIndex(index, length, null)
实现似乎更多的是面向设计而不仅仅是功能。
其原因主要可能是 Preconditions.checkIndex 被标记为 @HotSpotIntrinsicCandidate 这意味着在内部使用此方法时会寻求代码性能改进。
另外,可以注意到所有不可变列表 - 包含0(空),1,2或N个元素,使用工厂方法创建 of 利用了 Objects.checkIndex(int index, int length) 最终依赖于上述方法调用可能会进行一些内部优化。
简要说明 HotSpotIntrinsicCandidate 来自图书馆: -
该 @HotSpotIntrinsicCandidate 注释特定于
HotSpot虚拟机。它表示注释的方法可能(但不保证)由HotSpot VM中介化。
如果HotSpot VM替换带注释的方法,则会使方法本身化
手写汇编和/或手写编译器IR的方法
- 编译器内在 - 以提高性能。
该 @HotSpotIntrinsicCandidate 注释是Java的内部
图书馆,因此不应该有任何相关性
应用代码。
除非我在这里遗漏了一些明显的东西,否则这更简单。它与以下内容相同:
// this will not compile, *even* if test throws the Exception always
public String s() {
test();
}
private void test() {
throw new RuntimeException("just because");
}
编译器无法分辨 test 永远都会抛出 RuntimeException 所以它需要一个 return 声明 s()。同样的事情发生在 switch 枚举的陈述,你必须提供一个 throw;即使你已经处理了这个枚举的所有案例。
这个代码btw用于 List0,打电话没有意义 get(x),因为列表中没有元素可靠。