Готовимся к Java 9. Обзор самых интересных улучшений

https://zeroturnaround.com/rebellabs/the-best-java-9-language-and-api-improvements/
  • Перевод


В эту среду, 30 августа, в офисе компании Oracle состоялась встреча JUG.ru с Олегом Шелаевым, Developer Advocate в компании ZeroTurnaround, которая делает JRebel и XRebel. Тема встречи — инструменты создания многопоточных программ на Java (от конструирования велосипедов и запуска потоков ручками, до ForkJoinPool-ов, зеленых потоков и транзакционной памяти).


Конечно, мы поинтересовались, какие фишки Java 9 считают в ZeroTurnaround наиболее полезными. В результате, разжились статьей, которую вы сейчас читаете. Оригинал статьи Олег опубликовал в блоге RebelLabs, там есть еще много интересного.


Итак, начали.


Мы долго ждали Java 9, и вот, релиз уже не за горами. Ура! Это был не самый простой путь, но тем не менее, даже самые жаркие споры о системе модулей потихоньку продвигаются вперед, и большинство участников приходят к согласию. Скорей всего, релиз состоится совсем скоро, например, 21 сентября 2017 года.


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


Дальше будет список наших любимых новшеств в Java 9 API. В принципе, чтобы понять суть, достаточно взглянуть на примеры кода. Но можно запустить JShell и самостоятельно все эти примеры, своими глазами взглянуть на результаты.


Запускай JShell, я подожду… готов? Нет еще? Окей… сделал? Все еще нет? Да, на разгорев нужно время… ок, запустилось, отлично! Начинаем.


Фабричные методы для коллекций


Одна из наиболее ожидаемых фишек Java 9 — возможность делать литералы коллекций, чтобы удобней записывать самые простые случаи. Шутка, конечно, мы же говорим о Java, литералов у нас нет, есть только статические фабричные методы. Тем не менее, теперь мы можем легко создавать List, Map и Set, используя готовые методы:


jshell> List.of(1, 2, 3)
$1 ==> [1, 2, 3]

jshell> Set.of(1, 2)
$2 ==> [2, 1]

jshell> Map.of("hello", "world")
$3 ==> {hello=world}

Это стало возможным благодаря появлению статических методов в интерфейсах (Java 8), использовать которые научились List, Map и Set.


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


jshell> List.of(1).getClass()
$4 ==> class java.util.ImmutableCollections$List1

Стримы


В Stream API добавили парочку очень полезных возможностей. В частности, методы dropWhile и takeWhile. Как можно предположить по названию, dropWhile выбрасывает элементы с начала и до тех пор, пока не будет выполнено условие, а takeWhile — забирает элементы вплоть до выполнения условия.


jshell> IntStream.range(1, 10).dropWhile(x -> x < 5).forEach(System.out::println)
5
6
7
8
9

Следующее полезное дополнение — метод iterate(). Он позволяет заменять циклы стримами. Нужно передать ему изначальные значение стрима, условие (когда нужно остановить итерации), и функцию перехода (как именно будет получаться следующий элемент).


jshell> IntStream.iterate(0, x -> x < 3, x -> x + 1).forEach(System.out::println)
0
1
2

Если вам вдруг хотелось делать вычисления с фиксированной точкой на стримах, эта мечта может исполниться в Java 9.


Optional


Если вдруг кто не помнит, как их использовать, у нас есть отличная шпаргалка. В Java 9 наконец-то добавили метод or(), позволяющий в одну строчку связывать разные Optional’ы, не опускаясь до постоянных проверок на isPresent().


public Optional<T> or(Supplier<? extends Optional<? extends T>> supplier)

jshell> Optional.empty().or(() -> Optional.of("RebelLabs"))
$5 ==> Optional[RebelLabs]

Следующее хорошее дополнение — возможность преобразовывать Optional в стрим, содержащий не более одного элемента. Это реально полезно, если хочется использовать ленивые стримы. В примере ниже можно увидеть разницу своими глазами. Если вызвать map() на Optional, маппинг произойдет мгновенно, а вот на стриме — нет.


jshell> Optional.of(1).map(x -> x * 3)
$10 ==> Optional[3]

jshell> Optional.of(1).stream().map(x -> x * 3)
$11 ==> java.util.stream.ReferencePipeline$3@67b92f0a

И наконец, у нас появился метод ifPresentOrElse. В Java 8, можно было определить поведение только для случая, когда значение Optional существует. В Java 9 стало возможно указать два разных Runnable, определяющих что делать, если значение существует, и если не существует.


jshell> Optional.empty().ifPresentOrElse(x -> System.out.println(x), () -> System.out.println("empty"));
empty

Completable future


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


Один из самых крутых методов — это copy(), который возвращает немутабельную копию этого CompletableFuture. В следующем примере, мы создаем CompletableFuture, делаем его копию и проверяем, что завершение копии не влияет на исходный объект. Это очень-очень полезно, когда создается асинхронный API, возвращающий CompletableFuture. Раньше нужно было знатно помучиться, обруливая ситуации, когда клиент может сам завершить CompletableFuture, возвращенное из такого API. Сейчас достаточно просто взывать метод copy().


jshell> CompletableFuture<String> future = new CompletableFuture<>()
future ==> java.util.concurrent.CompletableFuture@35d176f7[Not completed]

jshell> future.copy()
$15 ==> java.util.concurrent.CompletableFuture@4973813a[Not completed]

jshell> future.isDone()
$17 ==> false

jshell> $15.isDone()
$18 ==> false

jshell> $15.complete("JRebel")
$19 ==> true

jshell> $15.isDone()
$20 ==> true

jshell> future.isDone()
$21 ==> false

Но самое крутое в том, что остановка родителя распространяется на все копии!


jshell> CompletableFuture<String> future = new CompletableFuture<>()
future ==> java.util.concurrent.CompletableFuture@4bbfb90a[Not completed]

jshell> future.copy()
$24 ==> java.util.concurrent.CompletableFuture@5a8806ef[Not completed]

jshell> future.complete("XRebel")
$25 ==> true

jshell> $24.isDone()
$26 ==> true

Кроме того, наконец-то в них добавили таймауты. Работа с асинхронным API, без наличия встроенных функций работы с таймаутами, была весьма напряжной. В Java 9 стало возможным точно определять способ завершения CompletableFuture, после истечения вручную заданного промежутка времени.


jshell> CompletableFuture<String> future = new CompletableFuture<>()
future ==> java.util.concurrent.CompletableFuture@67205a84[Not completed]

jshell> future.completeOnTimeout("Isn't this amazing", 1, TimeUnit.SECONDS)
$28 ==> java.util.concurrent.CompletableFuture@67205a84[Not completed, 1 dependents]

jshell> future.isDone()
$29 ==> true

API управления процессами


До Java 9, управление процессами было совершено не таким кроссплатформенным, как хотелось бы верить. Работа с подпроцессами раньше была несколько кривой, и вот в Java 9 её наконец выпрямили. Java 9 добавляет класс ProcessHandle, который предоставляет API для анализа текущего процесса, других процессов, найденных по пиду, их дочерних процессов, и так далее. Просто посмотрите на пример:


jshell> ProcessHandle current = ProcessHandle.current();
current ==> 6349

jshell> current.pid()
$33 ==> 6349

jshell> current.info().\TAB
arguments()          command()            commandLine()        equals(              getClass()
hashCode()           notify()             notifyAll()          startInstant()       toString()
totalCpuDuration()   user()               wait(

jshell> current.info().command()
$34 ==> Optional[/Library/Java/JavaVirtualMachines/jdk-9.jdk/Contents/Home/bin/java]

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


Еще одна популярная задача, которую будет куда удобней делать в Java 9 — запуск кода сразу после того, как процесс завершился. Java 9 предлагает для этого воспользоваться новым методом:


CompletableFuture<Process> onExit()

Указываете, что же вы хотите сделать, и это просто работает. Нет больше слёзок и нестабильных чужих библиотек.


StackWalker


Возрадуйтесь, ненавистники исключений! Теперь можно работать со стектрейсами, не создавая объектов Exception. Добро пожаловать в StackWalker!


StackWalker дает возможность бродить по стеку, фильтровать его, и эффективно делать разные другие вещи. Этот пример выдернет верхние 5 элементов из стектрейса:


jshell> StackWalker.getInstance().walk(s -> s.limit(5).collect(Collectors.toList()));
$36 ==> [do_it$(java:36), jdk.jshell/jdk.jshell.execution.DirectExecutionControl.invoke(DirectExecutionControl.java:209), jdk.jshell/jdk.jshell.execution.RemoteExecutionControl.invoke(RemoteExecutionControl.java:116), jdk.jshell/jdk.jshell.execution.DirectExecutionControl.invoke(DirectExecutionControl.java:119), jdk.jshell/jdk.jshell.execution.ExecutionControlForwarder.processCommand(ExecutionControlForwarder.java:134)]

Улучшения в языке Java


Улучшаются не только API, но и сам язык. Во-первых, символ _(подчёркивание) больше не является корректным идентификатором. Если вы зачем-то его используете, придется перейти на двойное подчеркивание! (Подсказка: не делайте этого).


jshell> int _ = 1
|  Error:
|  as of release 9, '_' is a keyword, and may not be used as an identifier
|  int _ = 1
|      ^
|  Error:
|  reached end of file while parsing
|  int _ = 1
|           ^

jshell> int __ = 1;
__ ==> 1

Это для того, чтобы в будущем можно было заменять на подчеркивание ненужные (опциональные) параметры при вызове функции.


Интерфейсы тоже немного доработали. Интерфейсы в Java 9 смогут содержать приватные методы. В Java 8 мы получили возможность хранить некую общую логику в default-методах. Теперь мы сможем выделять общую логику и внутри интерфейсов, без необходимости создания вспомогательных классов.


Вот вам небольшой синтетический пример:


jshell> interface A { private int zero() { return 0;} default int one() { return zero() + 1;}}
|  created interface A

Ну и наконец, последнее новшество. Теперь можно использовать effectively final переменные в блоках try-with-resources. Это упрощает код, не нужно больше объявлять переменные внутри try. Просто работаете с ними в блоке try, и это компилируется.


boolean a() throws Exception { 
  Socket s = new Socket(); 
  try (s) { } 
  return s.isClosed();
}

После выполнения блока try, все упомянутые там AutoClosable закономерно закроются.


Заключение


Ура! Мы рассмотрели кучу всего, и это далеко не все новшества, появившиеся в Java 9. Тем не менее, перечисленные выше вещи кажутся нам наиболее полезными, и пользоваться ими будут при первой возможности.


Выпуск Java 9 готовится уже довольно давно, и всем нам пора хорошенько разобраться, как она на нас повлияет. Сейчас это уместно как никогда, учитывая, что режим работы с clasthpath останется неизменным, и переход на Java 9 может оказаться простым и безболезненным. Можно прямо сейчас скачать готовую сборку Java 9, разобраться с новыми API, распробовать их, и приготовиться к наступающему светлому будущему!


Авторы


Олег Шелаев — Java-разработчик и Developer Advocate в ZeroTurnaround. Когда не занимается написанием java agent-ов или тестов, пишет в блог RebelLabs или выступает на конференциях. В свободное время пытается продвигать науку в Тартуском университете, изучая проблемы динамических обновлений программ.

Метки:
JUG.ru Group 859,68
Конференции для взрослых. Java, .NET, JS и др. 18+
Поделиться публикацией
Комментарии 91
  • –16

    Друзья, внесу немного оффтопика сейчас, т.к. завтра будет поздно. Сегодня (31 августа) — последний день, когда на Joker 2017 всё еще можно купить билеты по вкусной летней стоимости. До конца дня остались считаные часы. Кто хотел определиться — определяйтесь сейчас.

    • +3
      Хорошая статья! на некоторых моментах прям выдохнул) но выбор между интерфейсом и абстрактным классом теперь кажется сложнее, есть ли однозначный ответ, когда что выбирать?
      • +1
        У интерфейса нет и не может быть состояния.
        • +7
          public interface Отрывать {
              AtomicInteger руки = new AtomicInteger(10);
              private static void заТакое() {
                  руки.set(11);
              }
          }
          
          • +2
            Ну и это поле будет public static final, то есть состояния у интерфейса всё равно нет.
            • 0
              оно ведь mutable
              • +3
                Ну состояние будет одно на весь classloader, а не на каждый объект, который реализует этот интерфейс.
                • +4
                  public interface StateInterface
                  {
                  	Map<StateInterface, Integer> states = new IdentityHashMap<>();
                  
                  	default int getState()
                  	{
                  		return states.getOrDefault(this, 0);
                  	}
                  
                  	default void setState(int state)
                  	{
                  		states.put(this, state);
                  	}
                  }
                  • +1
                    Да, работает. Netbeans думает, что states статический финальный, но реально просто финальный.
                    • 0

                      Он на самом деле статический.

                    • +1
                      так и в ногу можно попасть. Даже не особо целясь
                      • 0
                        в ногу по-моему всегда попадают не целясь в неё))
        • +1
          CompletableFuture<Process> onExit()

          Я правильно понимаю, что с помощью этой штуки можно сделать процесс-маклауд? :)
          • 0
            Множественное наследование всё ближе? >:D

            А если серьёзно, то какого чёрта класс интерфейса содержит метод, возвращающий какую-то «избранную» реализацию?

            — не туда написал. Интерфейс у хабра всё ещё не тотр.
            • +1
              в таких случаях принято комментарий целиком заменять на слово «del», и потом писать в правильное место. Их обычно не минусуют, потому что всем и так ясно, откуда пошла такая фигня
            • +5
              Борис Бритва, или Борис-Хрен-Попадешь, резкий, как удар серпом по яйцам, и жесткий, как удар молотом. Живой советский герб. Говорят, эту сволочь вообще невозможно убить.

              www.youtube.com/watch?v=n7itx7O3b_k
            • –2
              Половина или больше этих фич уже есть в Kotlin.

              Вот почему-то ничего не пишут, закрыли ли они кучу багов и реквестов по JavaFx.
              • +7
                При чем здесь вообще котлин? Все его фичи тоже уже были в других языках.
                • –3
                  При том, что, выходит, изменения в языке / stdlib уже почти не нужны при 100% Java <-> Kotlin interop — если кому нужен сахар, но возьмёт Котлин и будет использовать его. Или любой другой JVM-based язык и компилятор.
                  Можно было бы сосредоточиться на платформе и hardcore фичах, типа modularity, а не на языке. Тогда бы и апдейты, глядишь, быстрее выходили.

                  • +1
                    В одном из предыдущих срачей топиков путем докапывания до котлин-адепта выяснилось, что интероп все же совсем не 100%. Также как и у других jvm языков.

                    Тем кто пишет core-либы смириться и жить на старых возможностях языка? Стоит забить на тех, кому нравится java?
                    • –1
                      Пришлите ссылку на топик, пожалуйста, если не лень, я бы с удовольствием почитал. Есть, конечно, нюансы, но они достаточно в крайних случаях мешают жить.

                      Нет, на тех, кому нравится Java, не забить, претензии только к срокам выхода обновлений. Так-то это всё полезные безусловно вещи. Надеюсь, Гёц сотоварищи таки будут продвигать апдейты пошустрее.
                      Просто те, кому нравится ТОЛЬКО Java, должны понимать, что они вот с такой скоростью будут получать обновления и плюшки. Это, кроме всего прочего, означает, что молодёжь будет изучать другие языки тоже и с бОльшим удовольствием придёт туда, где пишут не только на чистой Java.
                      • +2
                        >Это, кроме всего прочего, означает, что молодёжь будет изучать другие языки тоже и с бОльшим удовольствием придёт туда, где пишут не только на чистой Java.

                        Слава богу, хипстеров нам в джаве только еще и не хватало. Пусть на джаваскрипте пишут.
                    • +3
                      100% Java <-> Kotlin

                      cool story, bro
                      • –2
                        :) Киньте ссылок на доказательства обратного, пожалуйста, если есть :)
                        • 0
                          ссылок нет. опыт есть. рекурсивные дженерики с котлином не пробовали поженить?
                          да и не рекурсивные, бывает, глючат. Comparable с дженериком ему чота не нравится.
                          «Добавьте мне override». Добавил. «Я не понимаю, зачем тут override» :)
                          Приходилось делать странные финты ушами, типа сделать интерфейс на котлине, от него занаследовать явавский класс, от него опять котлин, чтоб только удовлетворить компилятор.
                          • 0
                            Понятно, спасибо. Пока не пробовал с generics, попробую. Это какая версия была у вас?
                            • 0
                              последний релиз
                      • +2
                        фигню говорите.
                        Оракл хотел ввести модульность. Но им не дали говнокодеры, не желающие переписывать свои программы. //Red Hat и IBM
                        • 0
                          Имхо там слегка сложней.
                          Есть договоренность, что если спека всеми принята, то ее делают.
                          А тут получилось, что люди прямо перед выпуском напрямую отказались от своих слов, посчитав их глупостью.
                          И дело там не только в «переписывать программы», а в том, что изначальную спеку нужно делать куда масштабней и умней.
                          Обычная мелкая гражданская война, в которой все правы и неправы одновременно, а страдают вообще другие люди :)
                    • 0
                      Вот почему-то ничего не пишут, закрыли ли они кучу багов и реквестов по JavaFx

                      По состоянию на 2016 год (если не читали):
                      static.rainfocus.com/oracle/oow16/sess/1462485593256001c2xn/ppt/JavaFX%209%20-%20New%20and%20Noteworthy.pdf
                      • +2
                        Java нужна потому, что это Java. Язык с невероятно долгой совместимостью и неформальными гарантиями что новые фичи будут хорошо работать очень долго (может быть, те же фичи будут использовать наши внуки), с хорошо подогнанными друг другу фичами (проходят годы обсуждений, прежде чем какая-то фича попадает на публику), с поддержкой Oracle, ну и в конце концов — это язык, на котором говорит большинство разработчиков в мире. Котлин — хороший язык, но он не об этом. Тем, кому нужна Java, нужна именно Java.
                      • 0
                        -> IntStream.range(1, 10).dropWhile(x -> x < 5).forEach(System.out::println)
                        |  Error:
                        |  cannot find symbol
                        |    symbol:   variable IntStream
                        |  IntStream.range(1, 10).dropWhile(x -> x < 5).forEach(System.out::println)
                        |  ^-------^
                        

                        Ubuntu 16.04


                        jshell 9-internal
                        
                        java -version
                        java version "9"
                        Java(TM) SE Runtime Environment (build 9+181)
                        Java HotSpot(TM) 64-Bit Server VM (build 9+181, mixed mode)
                        • +1
                          java.util.stream.IntStream.range(1, 10).dropWhile(x -> x < 5).forEach(System.out::println)
                          • 0

                            Спасибо, буду дальше изучать java

                        • –1
                          JRE станет еще более параноидальным?
                          • +1
                            Если Вы о системе модулей, то ДА.
                            • –1
                              Я о том, что я не Java-программист, а простой админ, и у меня есть горстка не нового, но вполне работоспособного железа, которое управляется через Java-апплеты, и с каждым мажорным релизом их всё сложнее запустить, потому что обновлений к этим железкам уже никто не выпустит, а параноики из Oracle не дают возможности отключить проверки, которые мешают запускать апплеты, и вообще мне не нужны.
                              • +2
                                Врядли апплеты можно закопать еще глубже, чем их уже закопали, так что нововведения уже совсем не о том.
                                (хотя я лично скорблю — хороня флеш уже сколько баянов порвали, а такие вкусные апплеты, имхо с меньшими проблемами безопасности, убили прямо в расцвете их сил)

                                Но также я наблюдаю развитие языков программирования как платформ. Java, увы, полностью исчезла из интернета, ради которого создавалась, и ушла в глухой сервер-энтерпрайз и мобайл(андроид).
                                • 0
                                  Что, если специально для старого железа держать под рукой старый браузер и старую яву для него?
                                  • 0
                                    Со старой и дурак сможет.
                            • 0

                              эт божественно

                              • +4
                                jshell> Map.of("hello", "world")
                                $3 ==> {hello=world}
                                

                                Полна боли и страдания жизнь без кортежей и/или классов данных.
                                • +3

                                  Да, поэтому:
                                  1) в конпеляторе есть исследование литералов: http://openjdk.java.net/jeps/186 (это именно исследование, а не финальная спека). Она прям напрямую связана, с обсуждаемой здесь фичей convenience methods (http://openjdk.java.net/jeps/269). Фичу курирует Гёц.
                                  2) уже есть проротипы type values, я писал о них недавно, и буду еще. Фичу курирует Гёц же, и Роуз.


                                  Короче, всё будет, но не мгновенно. Возможно, ускорение релизного цикла, о котором недавно писал Рейнхольт, позволит выкатить подобные mast-have фичи поперед других, более масштабных, изменений, и мы увидим их в ближайшем будущем.

                                • 0

                                  Почему они просто в библиотеку не добавили методы Optional? Зачем ждать новой версии языка?

                                  • +1

                                    Это не новая версия языка, это новая версия платформы Java, куда входит и язык, и стандартная библиотека, и тулинг (jshell, например).

                                    • 0
                                      К счастью, в Java мире нету апгрейдов стандартной библиотеке в отрыве от выпуска новой версии платформы.
                                      Любое изменение SDK должно быть только в мажорных релизах, иначе будет хаос и про существование стабильности можно будет забыть.

                                      И да, ускорение релизного цикла – это было бы очень круто!
                                      Но с планами по развитию платформы, ускорение релизного цикла, это не такой простой шаг. Зарелизить те же Панаму или Валхаллу – это не так просто будет и скорее всего повлечет откладывания релизов на полгода-год.
                                      • 0
                                        Да это жесть просто «ой ребята мы тут лажанулись и теперь видим что там необходимо было два метода добавить чтобы ада избежать, но у нас релизный цикл и сверх надежность, так что вы там держитесь. А в следующей версии мы опять что-то забудем и не дадим вам скучать.» :D
                                        • 0

                                          они на полугодовой цикл переходят

                                          • 0
                                            Все не так радужно как хотелось бы, но и не так мрачно, как вы описали.

                                            Некоторые фичи обкатываются месяцами перед тем, как попадут в публичный API. Если она не проходит паблик ревью, то ее заворачивают на доработку. Не стоит забывать, что за разработкой и развитием Java/JVM/JDK стоит очень много людей и компаний.

                                            А вот если фича попадает в публичный API, то ее уже оттуда и не вытянуть. Годами будет @deprecated висеть. И что хуже, эту фичу придется поддерживать, чтобы не сломалась и новый функционал нужно делать таким, чтобы не сломал @deprecated :(
                                            • 0

                                              А потом программисты начнут использовать эти два метода, а пользователи начнут жаловаться, почему это у них новая версия программы падает с NoSuchMethodError. А программисты им такие, да, теперь вам каждую неделю надо обновлять JRE, чтобы пользоваться нашим софтом.

                                        • +6

                                          Я один прочитал как JS hell?

                                          • +1
                                            осталось только впилить шугара а ля json и плавающий контекст this
                                          • +7

                                            Выглядит и звучит так же, как когда чиновники говорят о прорывах которые в других странах появились уже 10 лет назад.)
                                            Что например мешало добавить удобные методы для создания и манипуляции коллекциями раньше, мне не понятно.

                                            • +3
                                              святая заповедь стабильного апи в пределах мажорной версии.
                                              • 0

                                                Читайте дискуссии на эту тему в core-libs-dev. Много что мешало.

                                              • 0
                                                Что за приватные методы в интерфейсах?
                                                P.S. Понял: вероятно, общие куски кода для default-методов.
                                                • +1
                                                  просто делаешь приватный метод, и он работает. private static тоже.
                                                • +1
                                                  как скоро мы увидим что-то вроде for(x -> 0; x -> x < 10; x -> x+1).forEach(System.out::println)?
                                                  • 0
                                                    когда носители ФГМ набигут
                                                    • +1

                                                      уже работает. IntStream.iterate(0, x -> x < 10, x -> x + 1).forEach(System.out::println)

                                                    • +5
                                                      приватные методы в интерфейсах

                                                      Ребята, пора уже честно признаться — вам очень не хватало множественного наследования примесей, но вы стесняетесь вводить это бгмерзкое понятие и поэтому распидколбашиваете идеологию интерфейсов.
                                                      Интерфейсов, Карл! (запах горелого)
                                                      • 0
                                                        кстати, поправьте меня, если я неправ, но запилить некоторые примочки Optional и .of() можно собственными руками уже в java8
                                                        • 0
                                                          Раз пошла такая пьянка, предлагаю выпилить for
                                                          • 0
                                                            Почему не while?
                                                            • 0
                                                              Раз в год не грех выпилить одного барашка. While тоже хорош, но пускай еще подрастет
                                                          • 0
                                                            Выпиливать — не наш метод.
                                                            А вот без Properties, как в C#, до сих пор грустно. Как хорошо, что есть Lombok, правда, IDE его все так же не понимают…
                                                            • +1
                                                              Idea отлично его понимает через свой плагин
                                                              • 0
                                                                Гёц когда-то об этом говорил. Проблема в том, что проперти можно реализовать по-разному, и никакая из реализаций не подойдет всем желающим (включая желающих совместимости для легаси двадцатилетней давности). А маркетинговый эффект этой фичи будет минимальный, по сравнению с приложенными усилиями (т.е. если запилить что-то важное типа лямбд — это скорей будет стимулом поменять $languagename на Java, а вот введение пропертей — не особо)
                                                                • +2
                                                                  Зачем они? Только баги провоцируют. Читаешь код и хз что происходит пока все поля не прощелкаешь и не убедишься что это не функции на самом деле.
                                                                  • +1
                                                                    Idea + lombok plugin = Счастье!
                                                                    • 0
                                                                      Eclipse тоже понимает, но только после плясок с бубном)
                                                                    • 0

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

                                                                    • +1

                                                                      Java, ну когда в тебе уже появится автовывод типов, ну невозможно смотреть на портянки.

                                                                    • 0
                                                                      Это стало возможным благодаря появлению статических методов в интерфейсах (Java 8)

                                                                      Дефолтных?
                                                                      • 0
                                                                        public interface HelloWordable {
                                                                            public static void hello() {
                                                                                System.out.println("Hello World!");
                                                                            }
                                                                        }

                                                                        • +2
                                                                          С удивлением понял, что можно написать вот так:
                                                                          public interface Main {
                                                                          
                                                                              public static void main(String[] args) {
                                                                                  System.out.println("Hello World!");
                                                                              }
                                                                          
                                                                          }


                                                                          Или даже вот так:
                                                                          @SpringBootApplication
                                                                          @Configuration
                                                                          public interface TestApplication {
                                                                              public static void main(String[] args) {
                                                                                  ApplicationContext ctx = SpringApplication.run(TestApplication.class, args);
                                                                              }
                                                                          }
                                                                        • 0
                                                                          оу, прикольно) не знал про такое
                                                                      • 0

                                                                        А как там дело с модулями?

                                                                        • 0
                                                                          List.of(1, 2, 3)

                                                                          Неожиданно, что это возвращает неизменяемый List. Типичная ситуация в моём коде — создать List или Map с парой элементов, а потом добавить туда ещё несколько. Через List.of это сфейлится в рантайме с Exception-ом. Думаю, многие проограммисты на этом обожгутся.

                                                                          Как теперь лучше создавать изменяемые списки, вот так?
                                                                          new ArrayList(List.of(1, 2, 3))

                                                                          Лучше бы сделали ArrayList.of(1, 2, 3)
                                                                          • +1
                                                                            Вопрос в том, что стратегический план должен корректировать не только саму форму API, но и способ того, как люди пользуются Java. Направлять мир в правильное русло. Это один из смыслов существования архитектурных советов и выпуска ими рекомендаций. Если бы нужен был просто вспомогательный метод, сделать его не проблема, или уже стащить готовый из Гуавы.

                                                                            С точки зрения всеобщей схемы всего, верной практикой считается использование иммутабельных конструкций. Нужно всячески поощрять разработчиков к иммутабельности, а стиль программирования — к функциональной чистоте.

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

                                                                            Имхо, именно поэтому, для создания мутабельной версии выбрана специально переусложненная форма. Именно такая как у тебя в примере — использование копирующего конструктора поверх коллекции, полученной через convenience method.

                                                                            Я не чтобы оракул оракла, это чуть ли не открытым текстом сказано в JEP-269 Convenience Factories.

                                                                            В дальнейшем эти идеи могут быть развиты с помощью JEP-186 Collection Literals. Предлагается не мусорить с помощью List.of, а сразу писать List list = #[ 1, 2, 3 ];. Но это совершенно отдельный (тоже стратегический) вопрос.
                                                                            • 0
                                                                              IMHO, иммутабельные конструкции нужны, если для иммутабельных объектов GC поддерживает упрощенную сборку мусора по типу эрланга. А так…
                                                                              • 0
                                                                                А могли бы вы в двух словах рассказать, что за упрощенная сборка, которая основана на иммутабильности объектов?
                                                                                • 0
                                                                                  Следствием иммутабельности является то, что объект не может ссылаться на объекты, созданные позднее. Соотвественно, граф связей объектов становиться однонаправленным. В результате GC может работать быстрее и эффективнее. А работать ему придется много, поскольку иммутабельность.
                                                                                • 0

                                                                                  Сборка мусора — это деталь реализации, она никак не связана со спецификацией языка. Один и тот же метод стандартной библиотеки, возвращающий неизменяемую коллекцию, может выполняться на разных JVM с разными сборщиками мусора. Никто вам также не мешает форкнуть OpenJDK и написать свой сборщик мусора. Почему реализация стандартной библиотеки должна оглядываться на сборщики мусора?

                                                                                • 0

                                                                                  Думаю, не будет Collection literals. По крайней мере, не в ближайшие годы.

                                                                                • 0

                                                                                  А если мутабельный список, потокобезопасный он или нет? А добавление в начало или в середину дешёвое или нет? Реализаций списков много. А с Set и Map ещё хуже. Сохраняет ли порядок, сортирует ли ключи. Например, в JavaScript объекты сохраняют порядок вставки, а это дополнительные ненужные накладные расходы в 99% случаев. Сериализуемость, потокобезопасность. Можно ли в Java 9 сериализовать List.of(x) и десериализовать его потом в Java 8, получив аналог Collections.singletonList(x)? Много, много интересных вопросов влечёт такая фича. Это всё на тему того, почему 10 лет назад не сделали.


                                                                                  ArrayList.of(1,2,3) обсуждался, но он перекрывает List.of(1,2,3), а это нехорошо, когда один статический метод перекрывает другой, меняя семантику. Опять же привет старому поспешному дизайнерскому решению, что статический метод можно вызывать, используя подкласс в качестве квалификатора. Напишите вы class MySuperList extends ArrayList implements List, и что будет значить MySuperList.of(1,2,3)?

                                                                                  • 0
                                                                                    Ладно со списками, особенно красиво выглядит Set.of(), возвращающий иммутабельное множество, и
                                                                                    EnumSet.of(), возвращающий мутабельное

                                                                                Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.