Необязательный класс новых функций Java 8

Java

предисловие

Текст был включен в мой репозиторий GitHub, добро пожаловать, звезда:GitHub.com/bin39232820…
Лучшее время посадить дерево было десять лет назад, затем сейчас

болтовня

Сегодня начал писать серию новых фич Java 8. Как бы так сказать, в основном мало чего нового

  • Лямбда-выражения
  • функциональный интерфейс
  • ссылка на метод
  • Стрим поток
  • Необязательный класс
  • ключевое слово по умолчанию

Основные функции этих четырех — упростить написание кода, повысить производительность и т. д., но это также принесет хлопоты в обслуживании, потому что люди, которые в этом не разбираются, будут очень уставшими, но писать действительно вкусно. планирую поговорить о названии. Сегодня я собираюсь поговорить об этом необязательном классе, который предотвращает исключения нулевого указателя.Вы можете обратиться к следующим ссылкам для предыдущих разделов.
🔥Внутренние классы в Java, о которых вы не знали
🔥 Дженерики Java, которые вы должны знать
🔥Java8 новые функции лямбда-выражения, функциональный интерфейс, ссылка на метод и ключевое слово по умолчанию

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

Предварительное введение

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

Исходное решение: мы должны сначала определить, является ли возвращаемое значение нулевым, и можем использовать его в качестве параметра других методов только в том случае, если оно не является нулевым. Это именно то, что пытаются решить некоторые внешние API, такие как Guava. Некоторые языки программирования JVM, такие как Scala, Ceylon и т. д., уже решили эту проблему в основном API. Давайте посмотрим на пример

Вы чувствуете, что писать таким образом было бы намного лучше? Далее, давайте внимательно рассмотрим этот необязательный

Optional

Необязательный первый взгляд на свойства и конструкторы

 // 1、创建出一个Optional容器,容器里边并没有装载着对象
    private static final Optional<?> EMPTY = new Optional<>();

    // 2、代表着容器中的对象
    private final T value;

    // 3、私有构造方法
    private Optional() {
        this.value = null;
    }

    // 4、得到一个Optional容器,Optional没有装载着对象
    public static<T> Optional<T> empty() {
        @SuppressWarnings("unchecked")
        Optional<T> t = (Optional<T>) EMPTY;
        return t;
    }

    // 5、私有构造方法(带参数),参数就是具体的要装载的对象,如果传进来的对象为null,抛出异常
    private Optional(T value) {
        this.value = Objects.requireNonNull(value);
    }

    // 5.1、如果传进来的对象为null,抛出异常
    public static <T> T requireNonNull(T obj) {
        if (obj == null)
            throw new NullPointerException();
        return obj;
    }


    // 6、创建出Optional容器,并将对象(value)装载到Optional容器中。
    // 传入的value如果为null,抛出异常(调用的是Optional(T value)方法)
    public static <T> Optional<T> of(T value) {
        return new Optional<>(value);
    }

    // 创建出Optional容器,并将对象(value)装载到Optional容器中。
    // 传入的value可以为null,如果为null,返回一个没有装载对象的Optional对象
    public static <T> Optional<T> ofNullable(T value) {
        return value == null ? empty() : of(value);
    }

Таким образом, можно сделать вывод, что есть два способа создать дополнительный контейнер:

  • Вызовите метод ofNullable(), входящий объект может быть нулевым
  • Вызовите метод of(), входящий объект не может быть нулевым, иначе будет выброшено исключение NullPointerException.

Напишите метод для проверки, ха-ха

of

ofNullable

Простой способ дополнительных контейнеров

// 得到容器中的对象,如果为null就抛出异常
public T get() {
    if (value == null) {
        throw new NoSuchElementException("No value present");
    }
    return value;
}

// 判断容器中的对象是否为null
public boolean isPresent() {
    return value != null;
}

// 如果容器中的对象存在,则返回。否则返回传递进来的参数
public T orElse(T other) {
    return value != null ? value : other;
}

Эти три метода являются наиболее часто используемыми методами класса Optional и самыми простыми. (поскольку параметр не является функциональным интерфейсом)

см. использование

Так что это то, что мы используем для повторной калибровки в проекте, и это используется довольно часто.

Расширенное использование дополнительного контейнера (в основном из-за функционального программирования, упрощения кода)

Во-первых, давайте взглянем на метод ifPresent(Consumer super T> Consumer)

public void ifPresent(Consumer<? super T> consumer) {
    if (value != null)
        consumer.accept(value);
}

@FunctionalInterface
public interface Consumer<T> {
    void accept(T t);
}

методы orElseGet и orElseThrow

исходный код

// 如果对象存在,则直接返回,否则返回由Supplier接口的实现用来生成默认值
public T orElseGet(Supplier<? extends T> other) {
    return value != null ? value : other.get();
}


@FunctionalInterface
public interface Supplier<T> {
    T get();
}


// 如果存在,则返回。否则抛出supplier接口创建的异常
public <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) throws X {
    if (value != null) {
        return value;
    } else {
        throw exceptionSupplier.get();
    }
}

использование

public static void main(String[] args) {

    User user = new User();
    user.setName("六脉神剑");
    test(user);
}

public static void test(User user) {

    Optional<User> optional = Optional.ofNullable(user);

    // 如果存在user,则直接返回,否则创建出一个新的User对象
    User user1 = optional.orElseGet(() -> new User());

    // 旧写法
    if (user != null) {
        user = new User();
    }
}

метод фильтрации

исходный код

// 如果容器中的对象存在,并且符合过滤条件,返回装载对象的Optional容器,否则返回一个空的Optional容器
public Optional<T> filter(Predicate<? super T> predicate) {
    Objects.requireNonNull(predicate);
    if (!isPresent())
        return this;
    else
        return predicate.test(value) ? this : empty();
}


// 接口
@FunctionalInterface
public interface Predicate<T> {

    boolean test(T t);
}

использование

public static void test(User user) {

    Optional<User> optional = Optional.ofNullable(user);

    // 如果容器中的对象存在,并且符合过滤条件,返回装载对象的Optional容器,否则返回一个空的Optional容器
        Optional<User> optional = Optional.ofNullable(user);
        User user1 = optional.filter((value) -> "六脉神剑".equals(value.getName())).orElse(null);
        System.out.println(user1.getName());
}

map

исходный код

// 如果容器的对象存在,则对其执行调用mapping函数得到返回值。然后创建包含mapping返回值的Optional,否则返回空Optional。
public<U> Optional<U> map(Function<? super T, ? extends U> mapper) {
    Objects.requireNonNull(mapper);
    if (!isPresent())
        return empty();
    else {
        return Optional.ofNullable(mapper.apply(value));
    }
}


// 接口
@FunctionalInterface
public interface Function<T, R> {
    R apply(T t);
}

использование

public static void test(User user) {

    Optional<User> optional = Optional.ofNullable(user);

    // 如果容器的对象存在,则对其执行调用mapping函数得到返回值。然后创建包含mapping返回值的Optional,否则返回空Optional。
    optional.map(user1 -> user1.getName()).orElse("六脉神剑");
}

// 上面一句代码对应着最开始的老写法:

public String tradition(User user) {
    if (user != null) {
        return user.getName();
    }else{
        return "六脉神剑";
    }
}

flatMap

исходный код

// flatMap方法与map方法类似,区别在于apply函数的返回值不同。map方法的apply函数返回值是? extends U,而flatMap方法的apply函数返回值必须是Optional
public<U> Optional<U> flatMap(Function<? super T, Optional<U>> mapper) {
    Objects.requireNonNull(mapper);
    if (!isPresent())
        return empty();
    else {
        return Objects.requireNonNull(mapper.apply(value));
    }
}

Суммировать

Почувствуйте очарование опциона снова

public static void main(String[] args) {
    User user = new User();
    user.setName("六脉神剑");
    System.out.println(test(user));
}

// 以前的代码1.0
public static String test2(User user) {
    if (user != null) {
        String name = user.getName();
        if (name != null) {
            return name.toUpperCase();
        } else {
            return null;
        }
    } else {
        return null;
    }
}

// 以前的代码2.0
public static String test3(User user) {
    if (user != null && user.getName() != null) {
        return user.getName().toUpperCase();
    } else {
        return null;
    }
}

// 现在的代码
public static String test(User user) {
    return Optional.ofNullable(user)
            .map(user1 -> user1.getName())
            .map(s -> s.toUpperCase()).orElse(null);
}

filter, map или flatMap — это функция, значение параметра функции не должно быть нулевым. Таким образом, мы можем безопасно преобразовать его с помощью таких функций, как filter, map и flatMap, и, наконец, извлечь значение с помощью серий orElse, get, isPresent и ifPresent.

конец

Ну вот и все на сегодняшние факультативы. Все считают, что нет универсального и функционального интерфейса. Вы должны быть знакомы с ним. Если вы не знакомы с ним, действительно трудно этому научиться. Завтра я закончу лекцию по Stream 1.8. Это не сложно. Пока вы это понимаете, вы, естественно, будете это использовать.

ежедневные комплименты

Хорошо всем, вышеизложенное является полным содержанием этой статьи. Люди, которые могут видеть это здесь, всеталант.

Творить нелегко. Ваша поддержка и признание — самая большая мотивация для моего творчества. Увидимся в следующей статье.

Six Meridians Excalibur | Text [Original] Если в этом блоге есть какие-то ошибки, прошу покритиковать и посоветовать, буду очень признателен!