Heim >Java >javaLernprogramm >Neue API in Java 8 – Anwendungsbeispiele für Optional

Neue API in Java 8 – Anwendungsbeispiele für Optional

零下一度
零下一度Original
2017-05-24 11:40:222037Durchsuche

Wir wissen, dass Java 8 einige sehr nützliche APIs hinzugefügt hat, von denen eine optional ist. Wenn wir sie nicht ein wenig untersuchen, denken wir nur leicht, dass sie das Problem von NullPointException elegant lösen kann, also beginnt der Code so geschrieben werden

Optional4c8e0c17c3bd7e0081bb17cc795e1984 user = ......if (user.isPresent()) {return user.getOrders();

} else {return Collections.emptyList();

}

Dann müssen wir sagen, dass unser Denken immer noch am selben Punkt ist, aber wir denken instinktiv, dass es sich nur um einen Wrapper für die Benutzerinstanz handelt. Dies ist im Wesentlichen dasselbe wie Was wir zuvor geschrieben haben

User user = .....if (user != null) {return user.getOrders();

} else {return Collections.emptyList();

}

Es gibt keinen Unterschied. Dies ist die richtige Haltung für die Verwendung von Java 8 Optional Types, über die wir sprechen werden.

Während der Olympischen Spiele in Rio Ich erwähnte wiederholt, dass es ein Problem mit der roten Fünf-Sterne-Flagge gab, aber ich konnte es nicht erkennen, egal wie ich aussah. Was war das Problem? Später fand ich heraus, dass die Haltung des kleinen Sterns, der das Zentrum anbetete, falsch war. Daher dürfen wir Dinge, an die wir gewöhnt sind, nicht als selbstverständlich betrachten und werden überhaupt nicht das Gefühl haben, dass etwas falsch ist. Mit anderen Worten: Wenn wir auf Optional von Java 8 umsteigen, können wir nicht die Art und Weise erben, wie wir Null in der Vergangenheit behandelt haben. und wir sollten die neue und korrekte Haltung der korrekten Verwendung von Java 8 Optional beherrschen.

Um es ganz klar auszudrücken: Wenn wir noch die folgenden Methoden verwenden: Bei der Verwendung von Optional müssen Sie anfangen, sich selbst zu überprüfen

  1. Beim Aufruf der isPresent()-Methode

  2. Beim Aufruf der get()-Methode

  3. Wenn der optionale Typ ist Wird als Klassen-/Instanzattribut verwendet

  4. Wenn der optionale Typ als Methodenparameter verwendet wird

isPresent() und obj != null Dort Es gibt keinen Unterschied, unser Leben ist immer noch schockierend. Der Aufruf von get() ohne isPresent() erhält eine Warnung in 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.

(der Aufruf von Optional .get() verwendet nicht zuerst isPresent () um zu prüfen, ob der Wert verfügbar ist. Wenn Optional keinen Wert enthält, verwenden Sie get(). Es wird eine Ausnahme ausgelöst)

Von der Verwendung optionaler Typen als Attribute oder Methodenparameter wird in IntelliJ IDEA dringend abgeraten

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.

(Die Verwendung beliebiger Typen wie optionale Typen ist nicht ratsam, da Felder oder Methodenparameter Es ist nur als Methode der Klassenbibliothek konzipiert, die den Rückgabetyp eindeutig angeben kann, wenn möglicherweise kein Wert vorhanden ist. Optionale Typen können nicht serialisiert werden, und es treten Probleme auf, wenn sie als Feldtypen verwendet werden)

Also worauf wir uns bei Optional wirklich verlassen können, sollten andere Methoden außer isPresent() und get() sein:

public<U> Optional<U> map(Function<? super T, ? extends U> mapper)
public T orElse(T other)
public T orElseGet(Supplier<? extends T> other)
public void ifPresent(Consumer<? super T> consumer)
public Optional<T> filter(Predicate<? super T> predicate)
public<U> Optional<U> flatMap(Function<? super T, Optional<U>> mapper)
public <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) throws X

Ich bin einigermaßen zuversichtlich, was die oben genannten Methoden angeht ihre ungefähre Nutzungshäufigkeit. Bringen wir es in die richtige Reihenfolge.

Zuerst muss ich die drei Konstruktionsmethoden von Optional erwähnen: Optional.of(obj), Optional.ofNullable(obj) und explizit 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 时, 比如它是一个刚 new 出来的对象( Optional.of(new User(...)) ), 或者是一个非 null 常量时;  2. 当想为 obj 断言不为 null 时, 即我们想在万一 obj 为 null 立即报告 NullPointException 异常, 立即修改, 而不是隐藏空指针异常时, 我们就应该果断的用 Optional.of(obj) 来构造 Optional 实例, 而不让任何不可预计的 null 值有可乘之机隐身于 Optional 中.

现在才开始怎么去使用一个已有的 Optional 实例, 假定我们有一个实例 Optional4c8e0c17c3bd7e0081bb17cc795e1984 user , 下面是几个普遍的, 应避免 if(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 方法才叫优雅.

Ein paar andere: filter() wandelt unqualifizierte Werte in empty() um, flatMap() wird immer mit der Methode map() gepaart, orElseThrow() gibt direkt zurück, wenn ein Wert vorhanden ist, und wirft aus, wenn kein Wert vorhanden ist value Die gewünschte Ausnahme wird ausgelöst.

Ein Satz Zusammenfassung: Versuchen Sie bei Verwendung von Optional, die Methode Optional.get() nicht direkt aufzurufen. Optional.isPresent() sollte als private Methode betrachtet werden und davon abhängen andere Methoden wie Optional. .orElse() , Optional.orElseGet() , Optional.map() und andere solche Methoden.

Der beste Weg, Java 8 Optional zu verstehen, besteht darin, sich den Java-Quellcode anzusehen .util.Optional , Nur wenn Sie den Quellcode lesen, können Sie ihn wirklich sicher erklären. Wenn er wahr ist, wird der Wert verarbeitet, und wenn er falsch ist, wird nichts unternommen Empfehlungen】


1.

Teilen Sie den neu eingeführten optionalen Klasseninstanzcode in Java 8

2.

Analysieren Sie die optionale Klasseninstanz von Java 8 Anleitung

Das obige ist der detaillierte Inhalt vonNeue API in Java 8 – Anwendungsbeispiele für Optional. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn