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:-
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.
-
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.
-
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);
Predicate - kumukuha ng ilang value na T bilang argumento, nagbabalik ng boolean.
Halimbawa:boolean 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 можно нырнуть довольно глубоко, оставлю пару ссылочек, чтобы ребята, кто в душе тот ещё копатель, мог “поковыряться” на ура:
- статья о лямбда-выражениях в Java 8 на Хабре
- статья о лямбда-выражениях в Java в блоге Александра Косарева
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ов через :: Ссылки на методы бывают четырех видов:-
Ссылка на конструктор:
SomeObject obj = SomeObject::new
-
Ссылка на статический метод:
SomeObject::someStaticMethod
-
Ссылка на нестатический метод an object определенного типа:
SomeObject::someMethod
-
Ссылка на обычный(нестатический) метод конкретного an object
obj::someMethod
someList.stream()
.map(String::toUpperCase)
.forEach(System.out::println);
Для тех, кто хочет больше информации по ссылочным методам:
API Time
Появилась новая библиотека для работы с датами и временем — java.time. Новый 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 — с помощью этого типа можно достучаться до текущего времени и дате.
- Java и время: часть первая и вторая на Хабре
- Введение в API даты/времени в Java 8
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 Optional — отец холиваров
- Optional: Кот Шрёдингера в Java 8
- Новый класс Optional в Java 8, не панацея от NullPointerException
- Особенности Java 8: максимальное руководство на JavaRush — часть первая и вторая;
- Новое в Java 8 на Хабре;
- Топ-10 фич Java 8, о которых не говорят;
- Java 8 Tutorial.
Java 9
Итак, 21 сентября 2017 года мир увидел JDK 9. Данная Java 9 поставляется с богатым набором функций. Хотя нет новых концепций языка, новые API и диагностические команды определенно будут интересны разработчикам.JShell (REPL — read-eval-print loop)
Это реализация в Java интерактивной консоли, которая используется для тестирования функционала и использования в консоли разных конструкций, например интерфейсов, классов, enum, операторов и т.д. Для запуска JShell нужно лишь написать в терминале — jshell. Далее можно писать все, что позволит нам фантазия: С помощью 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а. Модульность реализуется на разных уровнях:- Языка программирования.
- Виртуальной машины.
- Стандартного java API.
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 9. What нового?
- Java 9: новые возможности
- Java 9 — Вы уже перешли? Нет? И не надо ...!?
- Сандер Мак о переходе к Java-модулям
Java 10
Итак, спустя шесть месяцев после выпуска Java 9, в марте 2018 года (помню How вчера), на сцену выходит Java 10.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 там лежит. Посвящается тем, кто хочет ближе познакомиться с данным функционалом:
- Java 10 LocalVariable Type-Inference
- Первый контакт с «var» в Java 10
- 26 рекомендаций по использованию типа var в Java
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рованную версию самого себя. Копателям:- Глубокое погружение в новый JIT-компилятор Java
- Graal: How использовать новый JIT-компилятор JVM в реальной жизни
- Как работает Graal — JIT-компилятор JVM на Java
Паралельный G1
Сборщик мусора G1 конечно крут, спору нет, но есть и слабое место: он выполняет однопоточный полный цикл GC. В то время, когда вам нужна вся мощь оборудования, которое вы можете собрать для поиска неиспользуемых an objectов, мы ограничиваемся одним потоком. В Java 10 это исправor.Теперь GC теперь работает со всеми ресурсами, которые мы к нему добавляем (то есть, становится многопоточным). Для этого разработчики языка улучшor изоляцию основных исходников от GC , создав для GC хороший чистый интерфейс. Разработчикам данной милоты — OpenJDK, пришлось конкретно разгрести свалку в codeе, чтобы не только максимально упростить создание новых GC, но и дать возможность быстро отключать ненужные GC из сборки. Один из основных критериев успеха — отсутствие просадки по скорости работы после всех этих улучшений. Смотрим ещё: Другие нововведения:- Вводится чистый интерфейс сборщика мусора (Garbage-Collector Interface). Благодаря этому улучшается изоляция исходного codeа от разных сборщиков мусора, давая возможность интегрировать альтернативные сборщики быстро и «безболезненно»;
- An association исходников JDK в один репозиторий;
- Коллекции получor новый метод — copyOf (Collection), который возвращает неизменную копию это коллекции;
- Optional (и его разновидности) получил новый метод .orElseThrow();
- Отныне JVM знают о том, что они запускаются в контейнере Docker, и будут извлекать специфичную для контейнера конфигурацию, а не запрашивать саму операционную систему.
- Guide to Java 10
- 10 JDK 10 features Java developers should know
- What нового в Java 10: часть первая и вторая
GO TO FULL VERSION