Этот недавний вопрос переполнения стека от Yahor заинтриговал меня: как обеспечить во время компиляции Java 8, что сигнатура метода «реализует» функциональный интерфейс . Это очень хороший вопрос. Давайте предположим следующий номинальный тип:
|
1
2
3
4
|
@FunctionalInterfaceinterface 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
|
// OKLongHasher good = LongHashes::xorHash;LongHasher alsoGood = LongHashes::continuingHash;// YikesLongHasher 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 . |