JavaRush /Java Blog /Random-TL /Mula 8 hanggang 13: isang kumpletong pangkalahatang-ideya...

Mula 8 hanggang 13: isang kumpletong pangkalahatang-ideya ng mga bersyon ng Java. Bahagi 1

Nai-publish sa grupo
Mga kuting, kumusta sa lahat)) Kaya, ngayong 2020 na tayo, at kakaunti na lang ang natitira hanggang sa paglabas ng Java 14. Dapat mong asahan ang natapos na bersyon sa Marso 17, susuriin namin kung ano ang bago at kawili-wili doon pagkatapos ng katotohanan, ngunit ngayon gusto kong i-refresh ang aking memorya sa mga nakaraang bersyon ng Java. Anong bago ang dinala nila sa atin? Tingnan natin. Simulan natin ang pagsusuri sa Java 8, dahil ito ay medyo may kaugnayan at ginagamit sa karamihan ng mga proyekto. Из 8 в 13: полный обзор версий Java. Часть 1 - 1Dati, ang mga bagong bersyon ay inilabas tuwing 3-5 taon, ngunit kamakailan lamang ay gumamit ang Oracle ng ibang diskarte - "bagong Java tuwing anim na buwan." At kaya, bawat anim na buwan nakikita namin ang pagpapalabas ng mga feature. Mabuti man o masama, iba ang tingin ng lahat. Halimbawa, hindi ko masyadong gusto ito, dahil ang mga bagong bersyon ay walang maraming mga bagong tampok, ngunit sa parehong oras, ang mga bersyon ay lumalaki tulad ng mga kabute pagkatapos ng ulan. Kumurap ako ng ilang beses sa isang proyekto na may Java 8, at ang Java 16 ay inilabas na (ngunit kapag ito ay bihirang lumabas, ang mga bagong tampok ay naipon, at sa huli ang kaganapang ito ay pinakahihintay, tulad ng isang holiday: lahat ay tinatalakay ang bagong goodies at hindi mo ito madadaanan) . Kaya simulan na natin!

Java 8

Functional na Interface

Ano ito? Ang functional na interface ay isang interface na naglalaman ng isang hindi naipatupad (abstract) na pamamaraan. Ang @FunctionalInterface ay isang opsyonal na anotasyon na inilalagay sa itaas ng naturang interface. Kailangang suriin kung natutugunan nito ang mga kinakailangan ng isang functional na interface (may isang abstract na paraan lamang). Ngunit gaya ng nakasanayan, mayroon kaming ilang mga caveat: ang mga default at static na pamamaraan ay hindi napapailalim sa mga kinakailangang ito. Samakatuwid, maaaring mayroong ilang mga pamamaraan + isang abstract, at ang interface ay gagana. Maaari rin itong maglaman ng mga pamamaraan ng klase ng Bagay na hindi nakakaapekto sa kahulugan ng interface bilang functional. Magdaragdag ako ng ilang salita tungkol sa mga default at static na pamamaraan:
  1. Nagbibigay-daan sa iyo ang mga pamamaraan na may default na modifier na magdagdag ng mga bagong pamamaraan sa mga interface nang hindi sinisira ang kanilang kasalukuyang pagpapatupad.

    public interface Something {
      default void someMethod {
          System.out.println("Some text......");
      }
    }

    Oo, oo, idinagdag namin ang ipinatupad na pamamaraan sa interface, at kapag ipinatupad ang pamamaraang ito, hindi mo ito maaring i-override, ngunit gamitin ito bilang isang minana. Ngunit kung ang isang klase ay nagpapatupad ng dalawang interface na may isang ibinigay na pamamaraan, magkakaroon tayo ng isang compilation error, at kung ito ay nagpapatupad ng mga interface at nagmamana ng isang klase na may isang tiyak na magkaparehong pamamaraan, ang paraan ng parent class ay magkakapatong sa mga pamamaraan ng interface at ang pagbubukod ay hindi gagana.

  2. Ang mga static na pamamaraan sa isang interface ay gumagana katulad ng mga static na pamamaraan sa isang klase. Huwag kalimutan: hindi ka maaaring magmana ng mga static na pamamaraan, tulad ng hindi mo maaaring tawagan ang isang static na pamamaraan mula sa isang descendant na klase.

Kaya, ilan pang salita tungkol sa mga functional na interface at magpatuloy tayo. Narito ang mga pangunahing listahan ng mga FI (ang iba ay ang kanilang mga varieties):

    Predicate - kumukuha ng ilang value na T bilang argumento, nagbabalik ng boolean.

    Halimbawa:boolean someMethod(T t);

  • Consumer - kumukuha ng argumento ng uri T, walang ibinalik (walang bisa).

    Halimbawa:void someMethod(T t);

  • Supplier — ничего не принимает на вход, но возвращает некоторое meaning T.

    Пример: T someMethod();

  • Function — принимает на вход параметр типа Т, возвращает meaning типа R.

    Пример: R someMethod(T t);

  • UnaryOperator — принимает аргумент Т и возвращает meaning типа Т.

    Пример: T someMethod(T t);

Stream

Стримы — это способ обрабатывать структуры данных в функциональном стиле. Как правило это коллекции (но можно использовать их в других, менее распространённых ситуациях). Более понятным языком, Stream — это поток данных, который мы обрабатываем How бы работая со всеми данными одновременно, а не перебором, How при for-each. Давайте рассмотрим небольшой пример. Предположим, у нас есть набор чисел, которые мы хотим отфильтровать (меньше 50), увеличить на 5, и из оставшихся вывести в консоль первые 4 числа. Как бы мы это провернули раньше:
List<Integer> list = Arrays.asList(46, 34, 24, 93, 91, 1, 34, 94);

int count = 0;

for (int x : list) {

  if (x >= 50) continue;

  x += 5;

  count++;

  if (count > 4) break;

  System.out.print(x);

}
Вроде codeа не так ужи много, а логика уже немного путанная. Посмотрим, How это будет выглядеть с помощью стрима:
Stream.of(46, 34, 24, 93, 91, 1, 34, 94)

      .filter(x -> x < 50)

      .map(x -> x + 5)

      .limit(4)

      .forEach(System.out::print);
Stream-ы сильно упрощают жизнь, сокращая объем codeа и делая его более читаемым. Кто желает более детально углубиться в эту тему вот неплохая (я бы даже сказал отличная) статья на эту тему.

Lambda

Пожалуй, самой важной и долгожданной фичей является появление лямбд. What такое лямбда? Это блок codeа, который можно передать в различные места, исходя из этого он может быть выполнен позже столько раз, сколько потребуется. Звучит довольно запутанно, не так ли? Проще говоря, с помощью лямбд, можно реализовывать метод функционального интерфейса (такая себе реализация анонимного класса):
Runnable runnable = () -> { System.out.println("I'm running !");};

new Thread(runnable).start();
Как шустро и без лишней волокиты мы реализовали метод run(). И да: Runnable — это функциональный интерфейс. Также лямбды использую в работе со стримами (How в примерах со стримами выше). Не будем сильно углубляться, так How можно нырнуть довольно глубоко, оставлю пару ссылочек, чтобы ребята, кто в душе тот ещё копатель, мог “поковыряться” на ура:

foreach

В Java 8 появился новый foreach, который работает с потоком данных How и стрим. Вот пример:
List<Integer> someList = Arrays.asList(1, 3, 5, 7, 9);

someList.forEach(x -> System.out.println(x));
(аналог someList.stream().foreach(…))

Method reference

Ссылочные методы — это новый полезный синтаксис, созданный чтобы ссылаться на существующие методы or конструкторы Java-классов or an objectов через :: Ссылки на методы бывают четырех видов:
  1. Ссылка на конструктор:

    SomeObject obj = SomeObject::new

  2. Ссылка на статический метод:

    SomeObject::someStaticMethod

  3. Ссылка на нестатический метод an object определенного типа:

    SomeObject::someMethod

  4. Ссылка на обычный(нестатический) метод конкретного an object

    obj::someMethod

Часто ссылки на методы используются в стримах instead of лямбд (ссылочные методы быстрее лямбд, но уступают в читаемости).
someList.stream()

        .map(String::toUpperCase)

      .forEach(System.out::println);
Для тех, кто хочет больше информации по ссылочным методам:

API Time

Появилась новая библиотека для работы с датами и временем — java.time. Из 8 в 13: полный обзор версий Java. Часть 1 - 2Новый API схож с любой Joda-Time. Наиболее значимые разделы этого API:
  • LocalDate — это конкретная дата, How пример — 2010-01-09;
  • LocalTime — время, учитывающее часовой пояс — 19:45:55 (аналог LocalDate);
  • LocalDateTime — комбо LocalDate + LocalTime — 2020-01-04 15:37:47;
  • ZoneId — представляет часовые пояса;
  • Clock — с помощью этого типа можно достучаться до текущего времени и дате.
Вот пара действительно интересных статей на эту тему:

Optional

Это новый класс в пакете java.util, обёртка (контейнер) для значений, фишкой которой является то, что она также может безопасно содержать null. Получение optional: Optional<String> someOptional = Optional.of("Something"); Если в Optional.of передавать null, у нас упадёт наше любимое NullPointerException. Для таких случаев юзают: Optional<String> someOptional = Optional.ofNullable("Something"); — в этом методе можно не бояться null. Далее, создание изначально пустого Optional: Optional<String> someOptional = Optional.empty(); Для проверки, пуст ли он, юзаем: someOptional.isPresent(); вернёт нам true or false. Выполнить определенное действие, если meaning есть, и ничего не делать, если значения нет: someOptional.ifPresent(System.out::println); Обратный метод, возвращающий переданное meaning, если Optional пуст (такой себе запасной план): System.out.println(someOptional.orElse("Some default content")); Продолжать можно очень и очень долго (благо, в Optional добавor методов How с щедрой руки), всё же на этом останавливаться не будем. Лучше я для затравочки пару ссылочек оставлю: Мы пробежались по самым известным нововведениям в Java 8 — это далеко не всё. Если вы хотите знать больше, то это я оставил для вас:

Java 9

Итак, 21 сентября 2017 года мир увидел JDK 9. Данная Java 9 поставляется с богатым набором функций. Хотя нет новых концепций языка, новые API и диагностические команды определенно будут интересны разработчикам. Из 8 в 13: полный обзор версий Java. Часть 1 - 4

JShell (REPL — read-eval-print loop)

Это реализация в Java интерактивной консоли, которая используется для тестирования функционала и использования в консоли разных конструкций, например интерфейсов, классов, enum, операторов и т.д. Для запуска JShell нужно лишь написать в терминале — jshell. Далее можно писать все, что позволит нам фантазия: Из 8 в 13: полный обзор версий Java. Часть 1 - 5С помощью JShell можно создавать методы верхнего уровня и использовать их внутри той же сессии. Методы будут работать, How и статические методы, за исключением того, что ключевое слово static можно упустить Подробнее — в руководстве по Java 9. REPL (JShell).

Private

Начиная с 9 версии Java, у нас появилась возможность использовать private методы в интерфейсах (default и static методы, так How другие мы попросту не можем переопределить из-за недостаточного доступа). private static void someMethod(){} try-with-resources Была модернизирована возможность обработки исключений Try-With-Resources:
BufferedReader reader = new BufferedReader(new FileReader("....."));
  try (reader2) {
  ....
}

Модульность (Jigsaw)

Модуль — это группа взаимосвязанных пакетов и ресурсов вместе с новым файлом дескриптора модуля. Данный подход используется, чтобы ослабить связанность codeа. Ослабление связи — ключевой фактор для удобства поддержки и расширяемости codeа. Модульность реализуется на разных уровнях:
  1. Языка программирования.
  2. Виртуальной машины.
  3. Стандартного java API.
JDK 9 поставляется с 92 модулями: мы можем юзать их or создать свои. Вот пара ссылок для более глубокого ознакомления:

Immutable Collection

В Java 9 стало возможным создание и заполнение коллекции одной строкой, при этом делая её immutable (ранее для создания immutable коллекции нам нужно было создать коллекцию, заполнить её данными, и вызов метода, например — Collections.unmodifiableList). Пример, такого создания: List someList = List.of("first","second","third");

Другие нововведения:

  • расширен Optional (добавлены новые методы);
  • появorсь интерфейсы ProcessHandle и ProcessHandle для управления действиями операционной системы;
  • G1 — дефолтный сборщик мусора;
  • HTTP клиент с поддержкой How HTTP/2 протокола и WebSocket;
  • расширен Stream;
  • добавлен фреймворк Reactive Streams API (для реактивного программирования);
Для более полного погружения в Java 9 советую почитать:

Java 10

Итак, спустя шесть месяцев после выпуска Java 9, в марте 2018 года (помню How вчера), на сцену выходит Java 10. Из 8 в 13: полный обзор версий Java. Часть 1 - 6

var

Теперь мы можем не предоставлять тип данных. Мы помечаем сообщение How var, и компилятор определяет тип messages по типу инициализатора, присутствующего справа. Данная фича доступна только для локальных переменных с инициализатором: ее нельзя использовать для аргументов методов, типов возвращаемых данных и т.д., так How там нет инициализатора для возможности определения типа. Пример var (для типа String):
var message = "Some message…..";
System.out.println(message);
var не является ключевым словом: по сути это зарезервированное Name типа, How и int. Пользова от var большая: объявления типов забирают на себя много внимания, не принося ниHowой пользы, а эта фича сэкономит время. Но в тоже время, если переменная получается из длинной цепочки методов, code становится менее читаемым, так How сходу неясно, что за an object там лежит. Посвящается тем, кто хочет ближе познакомиться с данным функционалом:

JIT-compiler (GraalVM)

Без лишних предисловий напомню: при запуске команды javac, приложение Java компorруется из Java-codeа в bytecode JVM, который является бинарным представлением applications. Но обычный процессор компьютера не может просто так выполнить bytecode JVM. Для работы вашей программы JVM нужен ещё один компилятор уже для этого bytecodeа, который преобразуется в машинный code, который процессор уже в состоянии использовать. В сравнении с javac, этот компилятор намного более сложный, но и в результате выдает более высококачественный машинный code. На данный момент OpenJDK содержит виртуальную машину HotSpot, у которой, в свою очередь, есть два основных JIT-компилятора. Первый — C1(клиентский компилятор), создан для более высокоскоростной работы, но при этом страдает оптимизация codeа. Второй — C2 (serverный компилятор). Страдает уже speed выполнения, но при этом code более оптимизирован. Когда используется Howой? С1 отлично подходит для настольных приложений, где нежелательны долгие паузы JIT-компилятора, а С2 — для долгоработающих serverных программ, в которых вполне сносно потратить больше времени на компиляцию. Многоуровневая компиляция — это когда сперва компиляция проходит с помощью С1, а результат проходит через С2 (используется для большей оптимизации). GraalVM — это проект, созданный для полной замены HotSpot. Мы можем рассматривать Graal How несколько связанных проектов: новый JIT-компилятор для HotSpot и новую виртуальную машину polyglot. Особенность данного JIT-компилятора заключается в том, что он написан на Java. Преимущество Graal компилятора — безопасность, то есть не сбои, а исключения, а не утечки памяти. Также мы будем иметь хорошую поддержку IDE, и мы сможем юзать отладчики, профorровщики or другие удобные инструменты. Помимо этого, компилятор вполне себе может быть независимым от HotSpot, и он сможет создавать более быструю JIT-скомпorрованную версию самого себя. Копателям:

Паралельный G1

Сборщик мусора G1 конечно крут, спору нет, но есть и слабое место: он выполняет однопоточный полный цикл GC. В то время, когда вам нужна вся мощь оборудования, которое вы можете собрать для поиска неиспользуемых an objectов, мы ограничиваемся одним потоком. В Java 10 это исправor.Теперь GC теперь работает со всеми ресурсами, которые мы к нему добавляем (то есть, становится многопоточным). Для этого разработчики языка улучшor изоляцию основных исходников от GC , создав для GC хороший чистый интерфейс. Разработчикам данной милоты — OpenJDK, пришлось конкретно разгрести свалку в codeе, чтобы не только максимально упростить создание новых GC, но и дать возможность быстро отключать ненужные GC из сборки. Один из основных критериев успеха — отсутствие просадки по скорости работы после всех этих улучшений. Смотрим ещё: Другие нововведения:
  1. Вводится чистый интерфейс сборщика мусора (Garbage-Collector Interface). Благодаря этому улучшается изоляция исходного codeа от разных сборщиков мусора, давая возможность интегрировать альтернативные сборщики быстро и «безболезненно»;
  2. An association исходников JDK в один репозиторий;
  3. Коллекции получor новый метод — copyOf (Collection), который возвращает неизменную копию это коллекции;
  4. Optional (и его разновидности) получил новый метод .orElseThrow();
  5. Отныне JVM знают о том, что они запускаются в контейнере Docker, и будут извлекать специфичную для контейнера конфигурацию, а не запрашивать саму операционную систему.
Вот еще несколько материалов для более детального ознакомления с Java 10: Раньше меня сильно путало то, что некоторые версии Java назывались 1.x. хотелось бы внести некую ясность: версии Java до 9 просто имели другую схему именования. Например, Java 8 также могут называть 1.8 , Java 5 — 1.5 и т. д. А сейчас мы видим, что с переходом на выпуски с Java 9 схема названий также изменилась, и версии Java больше не имеют префикса 1.x. Вот и конец первой части: мы прошлись по новым интересным фичам java 8-10. Давайте продолжим наше знакомство с самым свеженьким в следующем посте.
Mga komento
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION