Optional.get() kontra overbelastet Optional.orElseThrow()
Java 8 var en kæmpe forbedring af platformen, men en af de få fejl, vi lavede, var navngivningen af Optional.get()
, fordi navnet bare inviterer folk til at kalde det uden at ringe til isPresent()
, hvilket underminerer hele pointen med at bruge Optional
til at begynde med. (Hvis dette var den værste fejl, vi lavede i så stor en udgivelse, så klarede vi det ret godt.)
Under Java 9-tidsrammen foreslog vi at udfase Optional.get()
, men det offentlige svar på det var ... lad os sige koldt. Som et mindre trin introducerede vi orElseThrow()
i 10 (se https://bugs.openjdk.java.net/browse/JDK-8140281) som et mere gennemsigtigt navngivet synonym for den nuværende skadelige adfærd hos get()
. IDE'er advarer om ubetinget brug af get()
, men ikke på orElseThrow()
, hvilket er et skridt fremad i at lære folk at kode bedre. Spørgsmålet er i en vis forstand et "glas halvtomt" syn på den aktuelle situation; get()
er stadig problematisk.
Vi kunne godt tænke os at forbedre situationen yderligere i en fremtidig version, men det vil sandsynligvis tage noget tid at bringe flere af fællesskabet rundt.
Fra mit synspunkt, Optional.get()
er koden lugt. Meget ofte kombineret med Optional.isPresent()
, det besejrer fuldstændigt formålet og ideen med Optional.get()
. Her er en mere komplet begrundelse og diskussion:
http://royvanrijn.com/blog/2016/04/deprecating-optional-get/
Så brug simpelthen ikke Optional.get()
. Hvis du ønsker at returnere null
for den fraværende værdi, ring til Optional.orElse(null)
.
En alternativ metode til at få værdien af en valgfri i stedet for Optional.get
(som mere sandsynligt end ikke holder trit med brugerens forventninger) er at erstatte den med en mere omfattende API introduceret i JDK10 kaldet Optional.orElseThrow()
. Med forfatterens ord -
Optional.get()
er en "attraktiv gene" og er for fristende for programmører, hvilket fører til hyppige fejl. Folk forventer ikke, at en getter giver en undtagelse. En erstatnings-API til Optional.get()
med tilsvarende semantik bør tilføjes.
Optional<Integer> anyOddInStream = Stream.of(2, 4, 6, 8)
.filter(x -> x % 2 == 1)
.findAny();
// one could be well aware of the possible exception handling while reading this
var current = anyOddInStream.orElseThrow();
Bemærk :- Den underliggende implementering af begge disse API'er er den samme, men sidstnævnte læser tydeligere ud, at en NoSuchElementException
ville blive kastet som standard hvis værdien ikke er til stede, hvilket inlines til den eksisterende Optional.orElseThrow(Supplier<? extends X> exceptionSupplier)
implementering brugt af forbrugere som et eksplicit alternativ.