"но компилятор этого не знает" - какой смысл?
Я встретил такой код и комментарии в классе 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(...)
? Какая причина?
Ответы
Ответ 1
Возможно, это просто исключение дублирования кода, потому что иначе это будет что-то вроде:
new IndexOutOfBoundsException(outOfBoundsMessage(..., ...))
но outOfBounds*
методы private
, поэтому по дизайну кто-то должен вызывать обертки, такие как return Preconditions.checkIndex(index, length, null)
Ответ 2
Если мне не хватает чего-то очевидного здесь, это намного проще. Это то же самое, что:
// 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)
, потому что в списке нет никаких элементов.
Ответ 3
Реализация кажется более ориентированной на дизайн, чем просто функциональность.
Причины такого же могут быть связаны прежде всего с тем, что Preconditions.checkIndex
помечен как @HotSpotIntrinsicCandidate
, что означает, что исправление производительности кода запрашивается, когда этот метод используется внутри.
Кроме того, можно заметить, что весь неизменный список, содержащий 0 (пустой), 1, 2 или N элементов, созданный с использованием метода factory of
, использует Objects.checkIndex(int index, int length)
, который в конечном итоге полагается на вышеупомянутый вызов метода, чтобы, возможно, сделать некоторые внутренние оптимизации.
Кратко о HotSpotIntrinsicCandidate
из библиотеки: -
Аннотация @HotSpotIntrinsicCandidate
специфична для Виртуальная машина HotSpot. Он указывает, что аннотированный метод может (но не гарантированно) быть встроен в виртуальную машину HotSpot.
Метод встроен, если VM HotSpot заменяет аннотированный метод с рукописной сборкой и/или рукописным компилятором IR - встроенный компилятор - для повышения производительности.
Аннотация @HotSpotIntrinsicCandidate
является внутренней для Java библиотек и, следовательно, не должны иметь никакого отношения к код приложения.