我在网上遇到过这样的代码和评论 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)
,因为列表中没有元素可靠。