>  기사  >  Java  >  Java8 사용을 위한 올바른 자세

Java8 사용을 위한 올바른 자세

黄舟
黄舟원래의
2017-01-18 15:24:461395검색

Java 프로그래밍 언어

Java는 크로스 플랫폼 응용 소프트웨어를 작성할 수 있는 객체 지향 프로그래밍 언어로 1995년 5월 Sun Microsystems에서 출시한 Java 프로그래밍 언어이자 Java 플랫폼입니다. JavaEE(j2ee), JavaME(j2me), JavaSE(j2se))의 총칭.


우리는 Java 8에 몇 가지 매우 유용한 API가 추가되었다는 것을 알고 있으며 그 중 하나는 Optional입니다. 조금만 살펴보지 않으면 가볍게 생각할 수 있습니다. NullPointException.문제를 우아하게 해결해서 이렇게 코드가 작성되기 시작했습니다

Optional<User> user = ……
if (user.isPresent()) {
return user.getOrders();
} else {
return Collections.emptyList();
}

그렇다면 우리의 생각은 여전히 ​​같은 곳에 있다고 해야 하지만 본능적으로는 User를 위한 래퍼일 뿐이라고 생각합니다.

User user = …..
if (user != null) {
return user.getOrders();
} else {
return Collections.emptyList();
}

본질적으로는 차이가 없습니다. 이것이 우리가 이야기할 Java 8 Optional Type을 사용하는 올바른 자세입니다.

리우올림픽에서도 오성홍기에 문제가 있다고 뉴스에서 반복적으로 언급했는데, 아무리 봐도 잘못된 게 보이지 않았으나 나중에 보니 작은 별이 중심을 숭배하는 자세였다. 그러므로 우리는 익숙한 것을 당연하게 여겨서는 안 되며, 전혀 잘못된 것을 느끼지 않을 것입니다. 즉, Java 8 Optional로 전환하면 이전에 처리했던 방식을 상속받을 수 없습니다. null 과거에는 Java 8 Optional을 올바르게 사용하는 새롭고 올바른 자세를 익혀야 합니다.

직설적으로 말하면, 여전히 다음과 같은 Optional을 사용하고 있을 때 우리는 스스로 점검을 시작해야 합니다. 🎜>

isPresent() 메소드 호출 시

get() 메소드 호출 시

옵션 유형 클래스/인스턴스 속성으로 사용 시

옵션 유형 시 메소드 매개변수

isPresent() 및 obj != null 차이가 없습니다. 경고를 수신하는 get() 호출의 길을 열어주는 isPresent()가 없으면 우리 삶은 여전히 ​​충격적입니다. IntelliJ IDEA

Reports calls to java.util.Optional.get() without first checking with a isPresent() 
call if a value is available. If the Optional does not contain a value, get() will throw an exception. 
(调用 Optional.get() 前不事先用 isPresent() 检查值是否可用. 假如 Optional 不包含一个值, get() 将会抛出一个异常)

IntelliJ IDEA에서는 Optional 유형을 속성이나 메소드 매개변수로 사용하는 것을 강력히 권장하지 않습니다

Reports any uses of java.util.Optional<T>, java.util.OptionalDouble, java.util.OptionalInt, 
java.util.OptionalLong or com.google.common.base.Optional as the type for a field or a parameter. Optional was designed
 to provide a limited mechanism for library method return types where there needed to be a clear way to represent 
 “no result”. Using a field with type java.util.Optional is also problematic if the class needs to be Serializable, 
 which java.util.Optional is not. (使用任何像 Optional 的类型作为字段或方法参数都是不可取的. Optional 只设计为类库方法的,
  可明确表示可能无值情况下的返回类型. Optional 类型不可被序列化, 用作字段类型会出问题的)

따라서 Optional에서 실제로 신뢰할 수 있는 것은 isPresent() 및 get():

공용 선택적 맵(함수 super T, ? 확장 U> 매퍼)

공용 T orElse(T 기타)

public T orElseGet(공급자7b30dd0b2b885b76654676fe09d599db 기타 확장)

public void ifPresent(Consumer117c5a0bdb71ea9a9d0c2b99b03abe3e 소비자)

public Optional8742468051c85b06f0a0af9e3e506b5c 필터(Predicate117c5a0bdb71ea9a9d0c2b99b03abe3e predicate)

public Optional flatMap(Function super T, Optional

public (Supplier 예외 공급업체)는 서문을 발생시킵니다.

먼저 Optional.of(obj), Optional.ofNullable(obj) 및 명시적인 Optional.empty()의 세 가지 구성 방법을 언급해야 합니다.

Optional.of(obj): 들어오는 obj가 null일 수 없어야 합니다. 그렇지 않으면 역할을 입력하기 전에 NullPointerException이 발생합니다.

Optional.ofNullable(obj): 지능적인 방법을 사용합니다. , Optional 인스턴스를 생성하는 관용적인 방법입니다. 모든 사용자를 환영합니다. null을 전달하면 Optional.empty()를 얻게 됩니다. null이 아닌 경우 Optional.of(obj)를 호출하세요.

그게 바로 그 것입니다. 그냥 Optional.ofNullable(obj)을 사용하고 변경되지 않고 두 번째 변경 사항에 적응하는 방식으로 Optional 인스턴스를 구성하면 됩니다. 그렇지 않으면 왜 Optional.of를 사용합니까? (obj) 너무 노출되나요? 비공개일 수 있나요?

제 개인적인 관점은 다음과 같습니다. 1. Optional.of(obj)에 전달할 obj 매개변수가 매우 명확할 때 null, 예를 들어 방금 새로운 객체(Optional.of(new User( ...)))이거나 null이 아닌 상수입니다. 2. obj가 null이 아니라고 주장하려는 경우 즉, NullPointException 예외를 즉시 보고하고 obj가 null인 경우 Null 포인터 예외를 숨기는 대신 즉시 수정하고 싶습니다. Optional에 숨길 수 있는 기회를 이용하기 위해 값을 사용합니다.

지금 사용하는 방법 기존 Optional 인스턴스, Optional4c8e0c17c3bd7e0081bb17cc795e1984 사용자 인스턴스가 있다고 가정할 경우 다음과 같은 경우를 피하는 몇 가지 일반적인 방법이 있습니다. (user.isPresent()) { ... } else { ... } .

존재하면 반환되고, 없으면 기본값 제공

return user.orElse(null);  //而不是 return user.isPresent() ? user.get() : null;
return user.orElse(UNKNOWN_USER);

존재하면 반환되고, 존재하지 않으면 함수에 의해 생성됩니다

return user.orElseGet(() -> fetchAUserFromDatabase()); //而不要 return user.isPresent() ? user: fetchAUserFromDatabase();

存在才对它做点什么

user.ifPresent(System.out::println);

//而不要下边那样
if (user.isPresent()) {
  System.out.println(user.get());
}

map 函数隆重登场

当 user.isPresent() 为真, 获得它关联的 orders, 为假则返回一个空集合时, 我们用上面的 orElse, orElseGet 方法都乏力时, 那原本就是 map 函数的责任, 我们可以这样一行

return user.map(u -> u.getOrders()).orElse(Collections.emptyList())

//上面避免了我们类似 Java 8 之前的做法
if(user.isPresent()) {
  return user.get().getOrders();
} else {
  return Collections.emptyList();
}

map  是可能无限级联的, 比如再深一层, 获得用户名的大写形式

return user.map(u -> u.getUsername())
           .map(name -> name.toUpperCase())
           .orElse(null);

这要搁在以前, 每一级调用的展开都需要放一个 null 值的判断

User user = .....
if(user != null) {
  String name = user.getUsername();
  if(name != null) {
    return name.toUpperCase();
  } else {
    return null;
  }
} else {
  return null;
}

针对这方面 Groovy 提供了一种安全的属性/方法访问操作符 ?.

user?.getUsername()?.toUpperCase();

Swift 也有类似的语法, 只作用在  Optional 的类型上.

用了 isPresent() 处理 NullPointerException 不叫优雅, 有了  orElse, orElseGet 等, 特别是 map 方法才叫优雅.

其他几个, filter() 把不符合条件的值变为 empty(),  flatMap() 总是与 map() 方法成对的,  orElseThrow() 在有值时直接返回, 无值时抛出想要的异常.

一句话小结: 使用 Optional 时尽量不直接调用 Optional.get() 方法, Optional.isPresent() 更应该被视为一个私有方法, 应依赖于其他像 Optional.orElse(), Optional.orElseGet(), Optional.map() 等这样的方法.

最后, 最好的理解 Java 8 Optional 的方法莫过于看它的源代码 java.util.Optional, 阅读了源代码才能真真正正的让你解释起来最有底气, Optional 的方法中基本都是内部调用  isPresent() 判断, 真时处理值, 假时什么也不做.

以上就是使用 Java8 Optional 的正确姿势的内容,更多相关内容请关注PHP中文网(www.php.cn)!


성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.