Я обычно рассматриваю присутствие оператора instanceof в коде Java как « красный флаг », означающий, что использование instanceof в определенных ситуациях не обязательно является неправильным, но его использование иногда указывает на проблему проектирования, которая может быть решена более чистым способом, как описано в некоторых ресурсах, упомянутых в конце этого поста (в том числе в ресурсах о похожих функциях проверки типов в языках, отличных от Java).
Хотя я видел, что instanceof использовался несколько раз, когда это не нужно, я сталкивался с еще большим количеством ситуаций, когда было нелегко избежать instanceof . Это особенно верно при работе с унаследованными базами кода и некоторыми библиотеками и средами, в которых у меня нет возможности реорганизовать отношения между классами для поддержки интерфейсов, переопределения методов и других тактик, которые можно использовать для устранения необходимости в instanceof .
Очень распространенная техника, используемая с instanceof заключается в немедленном приведении к типу, проверенному в условном использовании instanceof . JEP 305 [«Сопоставление с образцом для instanceof (Preview)»] предоставляет пример этого общего образца, и я немного адаптировал этот пример здесь:
|
1
2
3
4
5
|
if (object instanceof String){ final String string = (String) object; // Do something with the 'string' variable typed as String} |
Бенджи Вебер писал о том, как использовать отражение и использовать лямбда-выражения для создания «экземпляров умных бросков», подобных котлинскому . К счастью, JDK 14 и JEP 305 имеют встроенную языковую поддержку (хотя и статус предварительного просмотра) для этого подхода.
JDK 14 представляет функцию предварительного просмотра, которая позволяет полностью реализовать instanceof условного и связанного преобразования в условном выражении. Эффект на приведенном выше примере кода показан ниже:
|
1
2
3
4
|
if (object instanceof String string){ // Do something with the 'string' variable typed as String} |
Эта функция предварительного просмотра доступна в ранних сборках JDK 14, и я использую JDK 14 раннего доступа 34 для моих примеров в этом посте.
Функция предварительного просмотра JEP 305 в JDK 14 — это небольшая хитрость, преимущество которой более очевидно в длинных условных выражениях if — then — else . Следующие два листинга кода обеспечивают сравнение «старого способа» вызова instanceof и явного приведения к «новому способу предварительного просмотра» использования instanceof сопоставления с образцом .
Традиционный instanceof сочетании с явным приведением
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
|
static void makeAnimalNoises(final Object animal){ if (animal instanceof Dog) { final Dog dog = (Dog) animal; out.println(dog.bark()); } else if (animal instanceof Cat) { final Cat cat = (Cat) animal; out.println(cat.meow()); } else if (animal instanceof Duck) { final Duck duck = (Duck) animal; out.println(duck.quack()); } else if (animal instanceof Horse) { final Horse horse = (Horse) animal; out.println(horse.neigh()); } else if (animal instanceof Cow) { final Cow cow = (Cow) animal; out.println(cow.moo()); } else if (animal instanceof Lion) { final Lion lion = (Lion) animal; out.println(lion.roar()); } else { out.println("ERROR: Unexpected animal: " + animal); }} |
Предварительный просмотр JDK 14 / JEP 305
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
|
static void makeAnimalNoises(final Object animal){ if (animal instanceof Dog dog) { out.println(dog.bark()); } else if (animal instanceof Cat cat) { out.println(cat.meow()); } else if (animal instanceof Duck duck) { out.println(duck.quack()); } else if (animal instanceof Horse horse) { out.println(horse.neigh()); } else if (animal instanceof Cow cow) { out.println(cow.moo()); } else if (animal instanceof Lion lion) { out.println(lion.roar()); } else { out.println("ERROR: Unexpected animal: " + animal); }} |
Полный код находится на GitHub, и есть разница между старым подходом и новым подходом предварительного просмотра .
Поскольку instanceof сопоставление с образцом является функцией предварительного просмотра, код, использующий эту функцию, должен быть скомпилирован с флагами javac --enable-preview и -source 14 . Это должно быть выполнено с флагом Java --enable-preview .
Вывод
Для получения более подробной информации о том, как реализована эта функция, см. Пост « RFR: JDK-8237528: Неэффективная компиляция сопоставления с образцом для instanceof ». Поддержка сопоставления с образцом для instanceof — это еще один шаг Amber к сокращенному шаблонному коду в Java.
Ресурсы по вопросам использования instanceof
- Java ‘instanceOf’: почему и как этого избежать в коде
- Вам действительно нужен instanceof?
- Использование instanceof в Java считается плохой практикой?
- Использование Instanceof — это в основном запах кода
- Экземпляр в условных выражениях: запах кода
- Остерегайтесь экземпляра оператора
- Насколько зло является «instanceof»?
- Проверка типа — это кодовый запах
|
Опубликовано на Java Code Geeks с разрешения Дастина Маркса, партнера нашей программы JCG . См. Оригинальную статью здесь: JDK 14 / JEP 305 instanceing Pattern Matching «Smart Casts» Мнения, высказанные участниками Java Code Geeks, являются их собственными. |