[Из песочницы] Обзор Java 9

Всем доброго времени суток. В ноябре 2017 в Санкт-Петербурге прошло одно из самых примечательных событий года для отечественных Java-разработчиков: конференция Joker. На конференции было озвучено много тем, такие как GC, Concurrency, Spring Boot, JUnit 5 и другие, презентации по которым вы можете найти в открытом доступе на сайте конференции. Перечислять все смысла нет, так как по каждому топику можно составить отдельную статью с примерами и выдержками. Поэтому остановимся на главном.

Основной темой были нововведения в Java 9: ей посвятили аж две лекции, по модулям, и по всему остальному. Саму девятку Oracle изначально планировали выпустить еще в середине лета 2016, однако релиз был перенесен сначала на полгода, а потом и вовсе на вторую половину 2017. И вот, 21 сентября 2017, выход девятки состоялся.

Данная статья представлена именно как обзор новоиспеченной джавы, так как тема сама по себе большая, требующая целого цикла статей, которые, несомненно, будут при поступлении просьб от трудящихся.

Итак, по порядку. Как говорилось выше, нововведения в девятке можно разделить на два блока: общий и модульный. Придерживаясь хронологии Joker, начнем с первого.

1. Появление литералов в коллекциях


На самом деле литералы в коллекциях можно использовать с 7 версии, никто не запрещает выполнить следующее, если у вас установлен ProjectCoin:

    List list = [3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5, 9];
    Set set = { 2, 7, 31, 127, 8191, 131071, 524287 };


В 9 версии вы можете использовать нечто подобное без каких-либо предварительных подготовок:

List piDigits = List.of(3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5, 9);
Set primes = Set.of(2, 7, 31, 127, 8191, 131071, 524287);


или

import static java.util.Map.*;
platonicSolids = ofEntries(entry(4, "tetrahedron"), entry(6, "cube"), ...);


Так же было сказано несколько слов о generic Pair, а вернее об их отсутствии. Однако в 9 появился усовершенствованный костыль использования мапы в качестве пары:

Map.entry(lowest, highest)


Ждем Project Valhalla.

2. Внедрение оператора Элвиса


На самом деле этот оператор реализован на Groovy на синтаксическом уровне, но если вы попробуете написать на джаве нечто подобное

        Person person = JohnGold ?: DefaultPerson;


компилятор предсказуемо ругнется. В девятке внедрили подобную логику, правда не на уровне синтаксиса. Ниже приведены два эквивалентных выражения на девятке и в уже привычном виде.

        
person = Objects.requireNonNullElse(JohnGold, DefaultPerson) //It will be work on Java 9
Optional maybePerson = JohnGold; // Familiar resolution
person = maybePerson.orElse(DefaultPerson);


3. Class Optional


Если кратко, этот класс для сбора not-null объектов: вместо того, чтобы проводить null-проверки, можно складывать объекты в данный контейнер, который автоматически будет отсеивать несуществующие объекты. Появился в Java 8 и вполне логично, что в новой версии появились улучшения для данного класса. Метод or интуитивно понятен: будет возвращен вызывающий объект, если он не нулевой, в противном случае вернется аргумент.

 maybePerson = maybePerson.or(() ->
JohnGold); // Another Optional


Следующий метод выполняет заданное действие над значением, если оно присутствует, в противном случае будет выполнено некое дефолтное значение.

maybePerson.ifPresentOrElse(System.out::println, // Consumer
() -> Runtime.exec("rm -rf /home")); // Runnable


Если значение присутствует, возвращает стрим только с этим значением, в противном случае стрим будет пустым.

Stream stream()


Возможность использовать flatMap для удаления нулевых результатов:


Stream users = people.map(Person::name)
.flatMap(Optional::stream);


4. Streams


Появился целый ряд методов API, из которых можно получить стримы: Scanner.tokens, Matcher.results, ServiceLoader.stream, LocalDate.datesUntil,
StackWalker.walk, ClassLoader.resources, Process.children/descendants,
Catalog.catalogs, DriverManager.drivers. В самих стримах тоже появились новые методы takeWhile, dropWhile, а также новые сборщики flatMapping, filtering.

5. IO, Regrexp


Тут все также масштабно. Появилась возможность считывать байты с поступающего потока

byte[] bytes = Files.newInputStream(path).readAllBytes();


Перенаправлять байты с входящего потока на исходящий: InputStream.transferTo (OutputStream).
Появилась возможность разбить принимаемый классом Scanner объект на токены в виде отдельных стримов:

Stream tokens = new Scanner(path).useDelimiter("\\s*,\\s*").tokens();


Matcher.stream и Scanner.findAll выдают поток найденных результатов:

Pattern pattern = Pattern.compile("[^,]");
Stream matches = pattern.match(str).stream().map(MatchResult::group);
matches = new Scanner(path).findAll(pattern).map(MatchResult::group);


Matcher.replaceFirst/replaceAll теперь могут принимать на вход функцию, согласно которой будет произведена перестановка:

String result = Pattern.compile("\\pL{4,}")
.matcher("Mary had a little lamb")
.replaceAll(m -> m.group().toUpperCase());
// Yields "MARY had a LITTLE LAMB"


6. Обработка процессов


Тут появился целый интерфейс ProcessHandle, позволяющий контролировать нативные процессы. С его помощью можно мониторить жив ли процесс, информацию о нем, лист детей и прочие плюшки. Зачем он нужен, когда есть абстрактный класс Process, спросите вы. На самом деле ProcessHandle предоставляет гораздо больше возможностей, нежели Process. Последний в свою очередь также предоставляет доступ к IOE потокам, что сказывается на производительности.

7. Немного синтаксических изменений


Интерфейсы теперь могут иметь методы с модификаторами доступа private, private static и судя по всему в скором времени совсем перестанут быть интерфейсами. Нижнее подчеркивание _ больше не может являться именем переменной — гайки закручиваются. И, наконец, поддержка try-with-resources


        void print (PrintWriter out, String[]lines){
            try (out) { // Effectively final variable
                for (String line : lines)
                    out.println(line.toLowerCase());
            }
        }


8. Старость


Появилось несколько деприкаций, куда же без этого. Классы Observable, Observer с новой версии будут считаться устаревшими, так же как и Object.finalize, Runtime.runFinalizersOnExit. Class.newInstance также теперь относят к Deprecated и аргументируют это тем, что он бросает проверяемые исключения конструктора без объявления их. Под ту же аннотацию попал весь Applet API, a также ряд модулей: java.activation, java.corba, java.transaction, java.xml.bind, java.xml.ws. Здесь были перечислены основные вещи, попавшие под аннотацию Deprecated и в презентацию Хорстмана, полный список всегда можно посмотреть у оракла.

9.Самая главная новость


System.getProperty("java.version")


Теперь этот код вернет значение »9», а не »1.9.0.».

Также в Java 9 появилась модульность, которая вызвала бОльший шум, чем все вышеперечисленное. И это неудивительно, так как статистика показывает, что это модульность была наиболее ожидаемой фичей среди разработчиков

image

Были вопросы что это вообще такое, как это будет взаимодействовать с Maven. Половина доклада ушла на обзор OSGi, вторая половина на обзор Jigsaw и объяснение почему это круто, превосходит по всем параметрам предмет первой половины доклада и то, что Jigsaw незаслуженно скромно принимается обществом. Судить об успешности этого проекта мы действительно можем только от общества, а пока нам остается ждать глобального перехода на Java 9, который, как сказали сами докладчики, будет происходить ближайшие 2–3 года. А пока можно посмотреть на самые ожидаемые изменения в следующей версии джавы и слушать шутки о том, будет ли она называться Java 10 или Java X.

image

© Habrahabr.ru