Metodo di incarto null-ritorno in Java con l'opzione a Scala?
-
11-10-2019 - |
Domanda
Supponiamo che io sono un metodo session.get(str: String): String
ma non so se lo restituirà una stringa o un valore nullo, perché viene da Java.
C'è un modo più semplice per trattare questa a Scala, invece di session.get("foo") == null
? Forse qualche magia applicare come ToOption(session.get("foo"))
e poi posso trattare in modo Scala come
ToOption(session.get("foo")) match {
case Some(_) =>;
case None =>;
}
Soluzione
metodo Option
Il compagno dell'oggetto apply
serve come una funzione di conversione da riferimenti nullable:
scala> Option(null)
res4: Option[Null] = None
scala> Option(3)
res5: Option[Int] = Some(3)
Altri suggerimenti
L'oggetto ha una Option
apply
method che fa esattamente questo:
var myOptionalString = Option(session.get("foo"));
Si noti che quando si lavora con oggetti Java non funzionerà come previsto:
val nullValueInteger : java.lang.Integer = null
val option: Option[Int] = Option(nullValueInteger)
println(option) // Doesn't work - zero value on conversion
val nullStringValue : String = null
val optionString: Option[String] = Option(nullStringValue)
println(optionString) // Works - None value
Questo è un argomento molto vecchio, ma una bella!
E 'vero che la conversione di qualsiasi risultato non eccezione di Prova a opzione si tradurrà in un Alcuni ...
scala> Try(null).toOption
res10: Option[Null] = Some(null)
... perché Prova non si tratta di controllo valori Null, ma solo un modo per gestire le eccezioni in modo funzionale.
Utilizzo di cercare di catturare un'eccezione e la conversione che per un opzione per comodità verranno visualizzati solo nel caso in cui nessuno un'eccezione accade.
scala> Try(1/0).toOption
res11: Option[Int] = None
Si vuole preservare i valori che vengono fuori prova. Che può essere nullo.
Ma è anche vero che la lib di serie è piuttosto confusa a volte ...
scala> Try(null).toOption
res12: Option[Null] = Some(null)
scala> Option(null)
res13: Option[Null] = None
Questo comportamento è un po 'incoerente, ma che tipo di riflette l'utilizzo di intented sia provare e l'opzione.
Si utilizza cercare di ottenere tutto ciò che esce da un'espressione che può generare eccezioni, e non si cura di fare un'eccezione per sé.
Il valore che può esca può benissimo essere nullo. Se toOption dato Nessuno, non si poteva distinzione fra un'eccezione e un null , e che non è abbastanza!
Standalone, si utilizza l'opzione di incapsulare l'esistenza o meno di qualcosa. Quindi, in questo caso, alcuni (null) vale None, e che abbia un senso, perché nulla in questo caso rappresenta l'assenza di qualcosa. Non c'è ambiguità.
E 'importante sottolineare che, in ogni caso referenziale trasparenza non è rotto dal .toOption è non la stessa opzione ()
Se si ha realmente bisogno di far rispettare ENTRAMBI sicurezza rispetto alle eccezioni e la sicurezza nullo, e il codice di davvero non ha bisogno di distinzione fra zero e un'eccezione , basta combinare entrambi i paradigmi! Perché beh, questo è ciò che si vuole, giusto?
Si può farlo in un modo ...
scala> Try(Option(null)).getOrElse(None)
res23: Option[Null] = None
scala> Try(Option(3/0)).getOrElse(None)
res24: Option[Int] = None
scala> Try(Option(3)).getOrElse(None)
res25: Option[Int] = Some(3)
... o in un altro ...
scala> Try(Option(null)).toOption.flatten
res26: Option[Null] = None
scala> Try(Option(3/0)).toOption.flatten
res27: Option[Int] = None
scala> Try(Option(3)).toOption.flatten
res28: Option[Int] = Some(3)
... o ridicolmente più brutto di loro anothers ...
scala> Option(Try(null).getOrElse(null))
res29: Option[Null] = None
scala> Option(Try(3/0).getOrElse(null))
res30: Option[Any] = None
scala> Option(Try(3).getOrElse(null))
res31: Option[Any] = Some(3)