Этот недавний вопрос переполнения стека от Yahor заинтриговал меня: как обеспечить во время компиляции Java 8, что сигнатура метода «реализует» функциональный интерфейс . Это очень хороший вопрос. Давайте предположим следующий номинальный тип:
1
2
3
4
|
@FunctionalInterface interface LongHasher { int hash( long x); } |
Тип навязывает кристально чистый контракт. Разработчики должны предоставить единственный метод с именем hash()
принимающий long
аргумент и возвращающий значение типа int
. При использовании лямбда-ссылок или ссылок на методы имя метода hash()
больше не имеет значения, и будет достаточно структурного типа long -> int
.
В своем вопросе Яхор хочет применить приведенный выше тип к трем статическим методам (пример, измененный мной):
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
|
class LongHashes { // OK static int xorHash( long x) { return ( int )(x ^ (x >>> 32 )); } // OK static int continuingHash( long x) { return ( int )(x + (x >>> 32 )); } // Yikes static int randomHash(NotLong x) { return xorHash(x * 0x5DEECE66DL + 0xBL); } } |
И он хотел бы, чтобы компилятор Java жаловался на третий случай, так как randomHash()
не «соответствует» LongHasher
.
Конечно, ошибку компиляции легко создать, фактически назначив static
методы в их функциональных обозначениях (ссылки на LongHasher
экземпляру LongHasher
:
1
2
3
4
5
6
|
// OK LongHasher good = LongHashes::xorHash; LongHasher alsoGood = LongHashes::continuingHash; // Yikes LongHasher ouch = LongHashes::randomHash; |
Но это не так кратко, как могло бы / должно быть. Ограничение типа должно быть наложено непосредственно на static
метод.
И как Java это делает?
С аннотациями, конечно!
Я собираюсь сделать ставку, что следующий шаблон появится в JDK 10:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
|
class LongHashes { // Compiles @ReferenceableAs (LongHasher. class ) static int xorHash( long x) { return ( int )(x ^ (x >>> 32 )); } // Compiles @ReferenceableAs (LongHasher. class ) static int continuingHash( long x) { return ( int )(x + (x >>> 32 )); } // Doesn't compile @ReferenceableAs (LongHasher. class ) static int randomHash(NotLong x) { return xorHash(x * 0x5DEECE66DL + 0xBL); } } |
Фактически, вы уже могли реализовать такую аннотацию сегодня и написать свой собственный процессор аннотаций ( или средство проверки JSR-308 ) для проверки этих методов. Ждем еще одну замечательную аннотацию !
Итак, кто готов поспорить, что у нас будет эта аннотация к JDK 10?
Ссылка: | Мы принимаем ставки: эта аннотация скоро появится в JDK от нашего партнера по JCG Лукаса Эдера в блоге JAVA, SQL и AND JOOQ . |