Java8 оценивает новый метод записи нулевого указателя
- Мало знаний, большой вызов! Эта статья участвует в "Необходимые знания для программистов«Творческая деятельность.
введение
В процессе разработки много раз будет встречаться проверка null.Если проверка null не выполняется, будет сгенерировано исключение NullPointerException. Следующий код может быть проблематичным для прямого использования.
user.getAddress().getProvince();
Когда пользователь нулевой, произойдет исключение нулевого указателя.Общее решение выглядит следующим образом:
if(user!=null){
Address address = user.getAddress();
if(address!=null){
String province = address.getProvince();
}
}
Этот способ написания уродлив Чтобы избежать вышеупомянутого уродливого способа письма, уродливый дизайн становится элегантным. Java8 предоставляет класс Optional для оптимизации написания.
Введение в API
Давайте сначала представим API, В отличие от других статей, эта статья использует аналогию и объединяет исходный код. В отличие от других статей, API перечислены один за другим, из-за чего люди не могут найти суть.
1. Необязательный(), пустой(), of(), ofNullable()
Соотношение между этими четырьмя функциями, таким образом, в группе памяти.
Позвольте мне сначала объяснить, Необязательный (значение T), то есть конструктор, который является закрытым и не может быть вызван извне. Оставшиеся три функции являются общедоступными разрешениями для вызова. Тогда суть Optional заключается в том, что он хранит внутри реальное значение, а при построении напрямую определяет, пусто ли его значение. Ну, это все еще немного абстрактно. Перейдите непосредственно к исходному коду конструктора Optional(T value), как показано на следующем рисунке.
Тогда исходный код of(T value) выглядит следующим образом
public static <T> Optional<T> of(T value) {
return new Optional<>(value);
}
То есть конструктор вызывается внутри функции of(T value). По исходному коду конструктора можно сделать два вывода:
- Необязательный объект, созданный функцией of(T value), по-прежнему будет сообщать об исключении NullPointerException, когда значение Value пусто.
- Необязательный объект, созданный функцией of(T value), может создавать необязательный объект в обычном режиме, когда значение Value не является пустым.
Кроме того, необязательный класс также поддерживает объект, значение которого равно нулю, что, вероятно, выглядит следующим образом.
public final class Optional<T> {
//省略....
private static final Optional<?> EMPTY = new Optional<>();
private Optional() {
this.value = null;
}
//省略...
public static<T> Optional<T> empty() {
@SuppressWarnings("unchecked")
Optional<T> t = (Optional<T>) EMPTY;
return t;
}
}
Итак, роль empty() заключается в том, что объект возвращает EMPTY. Ну так много можно сказать о напластовании, что роль ofNullable (значение T) верхнего источника
public static <T> Optional<T> ofNullable(T value) {
return value == null ? empty() : of(value);
}
Что ж, все должны понимать, что это значит. Разница по сравнению со значением of(T):
- Когда значение равно null, of(T value) сообщит об исключении NullPointerException;
- ofNullable(значение T) не генерирует исключение, ofNullable(значение T) напрямую возвращает ПУСТОЙ объект.
Означает ли это, что мы используем только функцию ofNullable вместо функции of в проекте?
Нет, вещь существует настолько естественно, что имеет ценность существования. При запуске не нужно скрывать NullPointerException. Вместо этого сообщите об этом немедленно, и в этом случае используется функция Of. Но я должен признать, что такие сцены действительно редки. Блогер использовал эту функцию только при написании тестовых случаев junit.
2. orElse(), orElseGet() и orElseThrow()
Эти три функции помещают группу памяти, которая вызывается, когда значение Value, включенное в конструктор, равно NULL. Использование Oralse и Oralseget выглядит следующим образом, что эквивалентно значению null, дает значение по умолчанию:
@Test
public void test() {
User user = null;
user = Optional.ofNullable(user).orElse(createUser());
user = Optional.ofNullable(user).orElseGet(() -> createUser());
}
public User createUser(){
User user = new User();
user.setName("zhangsan");
return user;
}
Разница между этими двумя функциями: когда пользовательское значение не равно null, функция orElse по-прежнему будет выполнять метод createUser(), а функция orElseGet не будет выполнять метод createUser(), вы можете проверить это самостоятельно.
Что касается orElseThrow, когда значение равно null, сразу генерируется исключение.
User user = null;
Optional.ofNullable(user).orElseThrow(()->new Exception("用户不存在"));
3. карта() и плоская карта()
Эти две функции помещаются в набор памяти, и эти две функции выполняют преобразование значения.
Перейти непосредственно к исходному коду
public final class Optional<T> {
//省略....
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));
}
}
//省略...
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));
}
}
}
Между двумя функциями в теле функции нет никакой разницы. Единственная разница заключается во входном параметре.Тип входного параметра, принимаемый функцией карты, — это Function, а тип входного параметра лоскутаMap — Function.
С точки зрения конкретного использования для карты:
Если структура пользователя выглядит следующим образом
public class User {
private String name;
public String getName() {
return name;
}
}
В это время имя пишется следующим образом
String city = Optional.ofNullable(user).map(u-> u.getName()).get();
Для плоской карты:
Если структура пользователя выглядит следующим образом
public class User {
private String name;
public Optional<String> getName() {
return Optional.ofNullable(name);
}
}
В это время имя пишется следующим образом
String city = Optional.ofNullable(user).flatMap(u-> u.getName()).get();
4. isPresent() и ifPresent(Consumer super T> потребитель)
Эти две функции вместе с памятью, т.е. isPresent определяют, является ли значение null значением, и когда значение ifPresent не пусто, что-то делают. Источник этих двух функций следующий
public final class Optional<T> {
//省略....
public boolean isPresent() {
return value != null;
}
//省略...
public void ifPresent(Consumer<? super T> consumer) {
if (value != null)
consumer.accept(value);
}
}
5. фильтр (предикат Predicate super T>)
Исходный код:
public final class Optional<T> {
//省略....
Objects.requireNonNull(predicate);
if (!isPresent())
return this;
else
return predicate.test(value) ? this : empty();
}
Метод фильтра принимает предикат для фильтрации значений, содержащихся в необязательном.Если содержащиеся значения удовлетворяют условиям, возвращается необязательный, в противном случае возвращается необязательный.пустой.
Использование заключается в следующем
Optional<User> user1 = Optional.ofNullable(user).filter(u -> u.getName().length()<6);
Как показано выше, если длина имени пользователя меньше 6, оно будет возвращено. Если оно больше 6, возвращается ПУСТОЙ объект.
реальный бой
Пример 1
В функциональном методе предыдущая запись
public String getCity(User user) throws Exception{
if(user!=null){
if(user.getAddress()!=null){
Address address = user.getAddress();
if(address.getCity()!=null){
return address.getCity();
}
}
}
throw new Excpetion("取值错误");
}
JAVA8 запись
public String getCity(User user) throws Exception{
return Optional.ofNullable(user)
.map(u-> u.getAddress())
.map(a->a.getCity())
.orElseThrow(()->new Exception("取指错误"));
}
Пример 2
Например, в основной программе предыдущий метод записи
if(user!=null){
dosomething(user);
}
JAVA8 запись
Optional.ofNullable(user)
.ifPresent(u->{
dosomething(u);
});
Пример 3
предыдущее написание
public User getUser(User user) throws Exception{
if(user!=null){
String name = user.getName();
if("zhangsan".equals(name)){
return user;
}
}else{
user = new User();
user.setName("zhangsan");
return user;
}
}
java8 письмо
public User getUser(User user) {
return Optional.ofNullable(user)
.filter(u->"zhangsan".equals(u.getName()))
.orElseGet(()-> {
User user1 = new User();
user1.setName("zhangsan");
return user1;
});
}
Другие примеры не перечислены один за другим. Тем не менее, используя это цепное программирование, хотя код элегантный. Однако логика не столь очевидна, а читабельность снижается, так что вы можете использовать ее по мере необходимости в своем проекте.