Обзор возможностей Java 8. Функциональные интерфейсы, лямбда-выражения, Stream и Time API

Обзор возможностей Java 8. Функциональные интерфейсы, лямбда-выражения, Stream и Time API

Версия Java 8 впервые была презентована еще 18 марта 2014 года и с этого времени стремительно набирает популярность среди разработчиков. Уже написано много книг по Java 8, которые раскрывают возможности нового API и тонкости функционального программирования. Однако в этой статье мы сделаем лишь краткий обзор основных нововведений Java 8.

Прежде всего вам нужно скачать и установить JDK 8. Сделать это можно бесплатно с официального сайта.

Обзор возможностей Java 8

Как обычно, мы приведем несколько фрагментов кода для лучшего понимания API и немного теории, поэтому не забудьте настроить Java 8 перед тем, как тестировать приведенный в статье код.

Метод forEach() интерфейса Iterable

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

Java 8 ввела новый метод forEach() в интерфейс java.lang.Iterable, который избавляет нас от лишнего кода и позволяет сосредоточиться только на бизнес-логике. Метод forEach() принимает объект  java.util.function.Consumer в качестве аргумента, который позволяет отделить бизнес-логику и дает возможность повторно использовать код.

Давайте посмотрим метод forEach() в действии:

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

Java 8. default и static методы в интерфейсах

Если присмотреться к методу forEach(), то можно заметить, что он определен в Iterable интерфейсе. А мы то знаем, что в интерфейсах нельзя писать реализацию метода. Но начиная с Java 8 в интерфейсах можно писать методы с реализацией. Для этого нужно использовать ключевые слова default и static. А сейчас посмотрим на реализацию метода forEach() в интерфейсе Iterable:

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

Обратите внимание, что в интерфейсах есть метод  log(String str) с реализацией.

Как видим, Interface1 содержит реализацию статического метода, который используется в реализации метода MyClass.log(). А сама Java 8 использует методы с ключевыми словами default и static в большой степени в Collection API.

Функциональные интерфейсы и лямбда-выражения в Java 8

Если вы обратите внимание на код выше, то заметите аннотацию @FunctionalInterface. Функциональные интерфейсы — новая концепция в Java 8. Интерфейс с одним абстрактным методом становится функциональным интерфейсом. Нам не нужно использовать аннотацию @FunctionalInterface, чтобы сделать наш интерфейс функциональным. Эта аннотация используется для того, чтобы избежать случайного добавления абстрактных методов в функциональный интерфейс. Этим она очень похожу на аннотацию @Override. Лучшим примером функционального интерфейса будет интерфейс java.lang.Runnable с одним абстрактным методом run().

Одним из главных преимуществ функционального интерфейса является возможность использовать лямбда-выражения. Мы можем создать экземпляр интерфейса с помощью анонимного класса, но код выглядит громоздким:

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

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

Новый пакет java.util.function был добавлен с целым букетом функциональных интерфейсов для лямбда-выражений. Сами же лямбда-выражения — это огромная тема, о которой мы поговорим в следующих статьях.

Java 8 Stream API

Java Stream API был добавлен в Java 8 для выполнения операций filter/map/reduce с коллекциями. Stream API позволяет как последовательные, так и параллельное выполнение.

Подробно об этой огромной теме читайте в отдельной статьей под названием «Полное руководство по Java Stream API«.

Java 8 Time API

В Java всегда было трудно работать с датой, временем и часовыми поясами. До сих по не было никаких стандартов или удобных API для с датой и временем в Java. Одним из лучших дополнений Java 8 является пакет java.time, который позволит упорядочить процесс работы со временем.

Пакет Java Time API предоставляет под-пакеты java.time.format, который обеспечивает классы для печати/парсинга даты и времени, а также java.time.zone, который обеспечивает поддержку временных зон и их правил изменения времени.

Следует отметить, что новый API для месяцев и дней недели построен на перечислениях (Enums), а не целочисленных константах (пора задуматься, если вы все еще не используете перечисления).

А для тех, кто хочет сразу затестить новый Time API, хочу посоветовать первым делом обратить внимание на DateTimeFormatter — один из наиболее полезных классов, который используется для преобразования объектов в строки.

Также изменения коснулись Многопоточности, Коллекций, Ввода/Вывода и нескольких вспомогательных классов Java Core. Подробнее об этих и других нововведениях читайте в следующих статьях на Javadevblog.com

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *