Вступление
Большинство предприятий и компаний, использующих Java, все еще работают на Java 7 или 8.
С марта 2018 года выпуски Oracle JDK появляются каждые 6 месяцев, что означает два основных выпуска в год, а это означает, что многие новые функции могут быть запущены в производство намного быстрее на стороне JDK, поэтому больше функций может быть запущено в конвейеры для глобального использования.
Это также означает, что запуск в Java 8 (который был выпущен во всем мире в марте 2014 года – это почти 6 лет назад) постепенно становится “слишком” устаревшим, и все же, благодаря внедрению API Streams, он выглядит намного современнее по сравнению с Java 7, он позволяет командам и разработчикам согласовывать более функциональный дизайн внутренней работы своих объектов, и это было столь необходимое улучшение языка, который великолепен и используется во всем мире, номер 1 в индексе TIOBE, и все же, был встречен все большим количеством критики и скептицизма пользователями конкурирующих технологий, таких как Kotlin и Scala, например.
Тот факт, что выпуски теперь происходят гораздо более быстрыми темпами, означает, что сам язык растет и совершенствуется, стремясь стать более современным, более чистым и прислушиваясь к тому, что все его пользователи хотели бы видеть добавленным, и все это с учетом предыдущих соображений дизайна, обратной совместимости и т.д. Это определенно непростая задача! Однако в последних выпусках в язык были внесены две вещи, которые сделают его гораздо более эргономичным и приятным в использовании.
Вывод типа локальной переменной
Эта функция связана с JEP 286 – Вывод типа локальной переменной и JEP 323 – Синтаксис локальной переменной для лямбда-параметров и это позволяет использовать новое зарезервированное ключевое слово var
для выполнения вывода типа локальной переменной.
Давайте предположим, что у нас есть функция, которая просто возвращает список массивов, содержащий список имен. В настоящее время наш код может выглядеть следующим образом:
import java.util.ArrayList; import java.util.Arrays; import java.util.List; public class Main { public static void main(String[] args) { ListsomeNames = getSomeNames(); System.out.println(someNames); } public static List getSomeNames() { return new ArrayList<>(Arrays.asList("Ann","John","Shelby")); } }
Итак, мы видим, что когда мы объявляем переменную некоторые имена
внутри нашей основной функции, нам нужно явно указать тип переменной как Список<Строка>
. Идеи с их функциями автозаполнения также автоматически установят тип переменной как Список<Строка>
.
Типы обычно выводятся по определенным критериям, которые позволяют компилятору “выводить” правильный тип, точно так же, когда мы создаем и используем наши собственные классы, они действуют как свои собственные типы из-за их поведения (т.Е. их общедоступных интерфейсов).
В данном конкретном примере переменная должна иметь тип Список<Строка>
потому что функция, возвращаемое значение которой присваивается этой переменной, относится к этому типу.
Что предлагает JEP 286, так это то, что для локальных переменных (и расширенных до лямбда-параметров) мы можем заставить компилятор выполнять вывод типа, т.Е. выводить тип для нас из контекста таким образом, чтобы теперь мы могли писать:
public class Main { public static void main(String[] args) { var someNames = getSomeNames(); System.out.println(someNames); } public static ListgetSomeNames() { return new ArrayList<>(Arrays.asList("Ann","John","Shelby")); } }
Обратите внимание, как мы используем недавно введенное ключевое слово var
, чтобы сократить объявление переменной.
Как только мы попытаемся добавить новый элемент в список, вот что покажет автозаполнение в IntelliJ:
Итак, мы видим, что все доступные методы являются частью интерфейса List
, который в точности соответствует типу возврата функции! Вывод типа работает.
Синтаксис локальной переменной для лямбда-параметров
Этот синтаксис также был расширен до параметров лямбда, чтобы обеспечить совместимость с выводом типа локальной переменной, описанным ранее.
Предположим, теперь мы хотим объединить наш список имен в одну строку. Для этого мы можем просто передать поток, а затем сократить список до одного элемента с помощью операции объединения:
Optionalz = someNames.stream().reduce((a, b) -> a + b);
Что предлагает следующий JEP, так это то, что для того, чтобы сделать выражения более единообразными, теперь мы можем ввести что-то вроде этого:
var z = someNames.stream().reduce((var a, var b) -> a + b);
Неявно типизированное лямбда-выражение должно использовать var для всех своих формальных параметров или ни для одного из них. Кроме того, var разрешен только для формальных параметров неявно типизированных лямбда-выражений — явно типизированные лямбда-выражения продолжают указывать типы манифеста для всех своих формальных параметров, поэтому некоторым формальным параметрам не разрешается иметь типы манифеста, в то время как другие используют var. Следующие примеры являются незаконными:
(var x, y) -> x.process(y) // Cannot mix 'var' and 'no var' in implicitly typed lambda expression (var x, int y) -> x.process(y) // Cannot mix 'var' and manifest types in explicitly typed lambda expression
Итак, мы изучили вывод типов и посмотрели, как это повлияет на то, как может начаться написание будущего кода на Java.
Улучшенный переключатель
Улучшая семантику и способ работы оператора switch
, Java на один шаг приближается к сопоставлению шаблонов, что позволяет более кратко и безопасно выражать общую логику в программе, а именно условное извлечение компонентов из объектов.
Предложение по улучшению JEP 325: Выражения переключения (предварительный просмотр) значительно упростит работу с оператором switch
за счет устранения “сквозного” поведения и обеспечения поддержки нескольких меток, разделенных запятыми, в одной метке переключателя.
В “старой Java” вот как мы могли бы написать оператор switch
, чтобы сообщить нам об определенных днях недели:
public static void daysOfWeek(int day){ switch (day) { case SATURDAY: case SUNDAY: System.out.println("weekend"); break; case MONDAY: System.out.println("oh no! Monday"); break; case FRIDAY: case TUESDAY: case THURSDAY: case WEDNESDAY: System.out.println("gotta work"); break; } }
Мы можем видеть разрыв
после каждого оператора печати, чтобы избежать провального поведения, и мы видим, что он также довольно подробный и содержит много кода для чтения, просто чтобы сделать некоторые утверждения о днях недели.
В новой Java вот как мы можем написать это:
public static void daysOfWeek(int day){ switch (day) { case SATURDAY, SUNDAY -> System.out.println("weekend"); case MONDAY -> System.out.println("oh no! Monday"); case TUESDAY, WEDNESDAY, THURSDAY, FRIDAY -> System.out.println("gotta work"); } }
Как мы видим, мы можем использовать новую форму метки переключения, написанную “регистр L ->”, чтобы указать, что только код справа от метки должен выполняться, если метка совпадает.
Это обеспечивает гораздо более компактную инструкцию переключения, более легкую для чтения и более близкую по дизайну к соответствию шаблону!
Мы также можем назначать выражения переключения переменным, таким как:
public static String daysOfWeek(int day){ return switch (day) { case SATURDAY, SUNDAY -> "weekend"; case MONDAY -> "oh no! Monday"; case TUESDAY, WEDNESDAY, THURSDAY, FRIDAY -> "gotta work"; default -> "";}; }
Обратите внимание, что нам нужна рука соответствия по умолчанию
в случае, если пользователь вводит целое число, которое не распространяется на другие случаи. Это очень похоже на конструкции сопоставления с образцом, такие как _ ->
языки, такие как, например, Haskell.
И это все!
Вывод
Мы рассмотрели идеи и усовершенствования трех предложений по улучшению Java, чтобы увидеть, как язык продолжает развиваться и стремится быть более простым в использовании и чтении, сохраняя при этом обратную совместимость со своими предыдущими версиями.
PS: Если вам это понравилось, я могу просмотреть будущие JEPs!
Оригинал: “https://dev.to/brunooliveira/bleeding-edge-java-improved-switch-and-local-type-inference-1do7”