Функции и улучшения Java 8

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

  1. Лямбда-выражения
  2. Функциональные Интерфейсы
  3. Методы по умолчанию
  4. Потоки Java 8
  5. Изменения API даты и времени Java 8
    5.1. Классы Date
    5.2. Временные метки и Duration классы

Лямбда-выражения

Лямбда-выражения известны многим из нас, кто работал над другими популярными языками программирования, такими как Scala. На языке программирования Java лямбда-выражение (или функция) — это просто анонимная функция, то есть функция без имени и без привязки к идентификатору.

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

Несколько основных видов синтаксиса лямбда-выражений следующие:

(parameters) -> expression 

(parameters) -> { statements; } 

() -> expression

Типичный пример лямбда-выражения будет выглядеть следующим образом:

//Эта функция принимает два параметра и возвращает их сумму

sum (x, y) -> x + y

Обратите внимание, что в зависимости от типа x и y мы можем использовать этот метод в нескольких местах. Параметры также могут соответствовать значению int, или Integer, или просто String. В зависимости от контекста он либо добавит два целых числа, либо объединит две строки.

Правила написания лямбда-выражений:

  1. Лямбда-выражение может иметь ноль, один или несколько параметров.
  2. Тип параметров может быть явно объявлен или может быть выведен из контекста.
  3. Несколько параметров заключены в обязательные круглые скобки и разделены запятыми. Пустые круглые скобки используются для представления пустого набора параметров.
  4. При наличии единственного параметра, если выводится его тип, использование круглых скобок необязательно.
  5. Тело лямбда-выражений может содержать ноль, один или несколько операторов.
  6. Если тело лямбда-выражения содержит один оператор, фигурные скобки не являются обязательными, а возвращаемый тип анонимной функции такой же, как и у основного выражения. Если в теле есть более одного оператора, то они должны быть заключены в фигурные скобки.

Функциональные Интерфейсы

Функциональные интерфейсы также называются интерфейсами с одним абстрактным методом (SAM Interfaces). Как следует из названия, функциональный интерфейс допускает в нем ровно один абстрактный метод.

Java 8 вводит аннотацию @FunctionalInterface, которую мы можем использовать для выдачи ошибок во время компиляции, если функциональный интерфейс нарушает контракты.

Пример функционального интерфейса

//Optional annotation
@FunctionalInterface
public interface MyFirstFunctionalInterface {
    public void firstWork();
}

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

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

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

Например, ниже приведен вполне допустимый функциональный интерфейс.

@FunctionalInterface
public interface MyFirstFunctionalInterface 
{
    public void firstWork();
 
    //Overridden from Object class
    @Override
    public String toString();                
 
    //Overridden from Object class
    @Override
    public boolean equals(Object obj);        
}

Методы по умолчанию

Java 8 позволяет нам добавлять неабстрактные методы в интерфейсы. Эти методы должны быть объявлены методами по умолчанию. Методы по умолчанию были введены в java 8, чтобы включить функциональность лямбда-выражения.

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

Давайте разберемся на примере:

public interface Moveable {
    default void move(){
        System.out.println("I am moving");
    }
}

Moveable интерфейс определяет метод move() и также предоставляет реализацию по умолчанию. Если какой-либо класс реализует этот интерфейс, то ему не нужно реализовывать свою собственную версию метода move(). Он может напрямую вызывать instance.move(). например

public class Animal implements Moveable{
    public static void main(String[] args){
        Animal tiger = new Animal();
        tiger.move();
    }
}
  
Output: I am moving

Если класс добровольно хочет настроить поведение метода move(), то он может предоставить свою собственную пользовательскую реализацию и переопределить метод.

Потоки Java 8

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

Streams API в Java 8 поддерживает другой тип итерации, где мы определяем набор элементов, подлежащих обработке, операции, которые должны выполняться над каждым элементом, и где должны храниться выходные данные этих операций.

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

List<String> items = ...; //Initialize the list
 
String prefix = "str";
 
List<String> filteredList = items.stream()
          .filter(e -> (!e.startsWith(prefix)))
          .collect(Collectors.toList());

Здесь items.stream() указывает, что мы хотим обрабатывать данные с использованием Streams API.

Изменения API даты и времени Java 8

Новые API-интерфейсы/ классы даты и времени (JSR-310), также называемые Three Men, просто изменили способ обработки дат в приложениях Java.

Классы Date

Класс Date даже устарел. Новыми классами, предназначенными для замены класса Date, являются LocalDate, LocalTime и LocalDateTime.

  1. Класс LocalDate представляет дату. Нет никакой информации о времени или часовом поясе.
  2. Класс LocalTime представляет время. Нет никакой информации о дате или часовом поясе.
  3. Класс LocalDateTime представляет дату и время. Нет никакой информации о часовом поясе.

Если мы хотим использовать функциональность данных с информацией о часовом поясе, то Lambda предоставляет нам дополнительные три класса, аналогичные приведенным выше, т.е. OffsetDate, OffsetTime и OffsetDateTime.

Смещение часового пояса может быть представлено в форматах “+05:30” или “Europe/Paris”. Это делается с помощью другого класса, то есть ZoneId.

LocalDate localDate = LocalDate.now();
LocalTime localTime = LocalTime.of(12, 20);
LocalDateTime localDateTime = LocalDateTime.now(); 

OffsetDateTime offsetDateTime = OffsetDateTime.now();
ZonedDateTime zonedDateTime = ZonedDateTime.now(ZoneId.of("Europe/Paris"));

Временные метки и Duration классы

Для представления конкретной временной метки в любой момент необходимо использовать класс Instant. Класс Instant представляет момент времени с точностью до наносекунд.

Операции с Instant включают сравнение с другим Instant и добавление или вычитание длительности.

Instant instant = Instant.now();
Instant instant1 = instant.plus(Duration.ofMillis(5000));
Instant instant2 = instant.minus(Duration.ofMillis(5000));
Instant instant3 = instant.minusSeconds(10);

Класс Duration — это совершенно новая концепция, впервые представленная на языке java. Он представляет собой разницу во времени между двумя временными метками.

Duration duration = Duration.ofMillis(5000);
duration = Duration.ofSeconds(60);
duration = Duration.ofMinutes(10);

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

Чтобы взаимодействовать с людьми, нам нужно получить большую продолжительность времени, представленную классом Period.

Period period = Period.ofDays(6);
period = Period.ofMonths(6);
period = Period.between(LocalDate.now(), LocalDate.now().plusDays(60));

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

Ваш адрес email не будет опубликован.

11 − 7 =