Null-Return-Methode in Java mit Option in Scala verpacken?


107

Angenommen, ich habe eine Methode, session.get(str: String): Stringaber Sie wissen nicht, ob sie Ihnen eine Zeichenfolge oder eine Null zurückgibt, da sie aus Java stammt.

Gibt es eine einfachere Möglichkeit, dies in Scala zu behandeln, anstatt session.get("foo") == null? Vielleicht gilt etwas Magie wie ToOption(session.get("foo"))und dann kann ich es in Scala wie behandeln

ToOption(session.get("foo")) match {
    case Some(_) =>;
    case None =>;
}


Antworten:


182

Die Methode des OptionBegleitobjekts applydient als Konvertierungsfunktion für nullfähige Referenzen:

scala> Option(null)
res4: Option[Null] = None

scala> Option(3)   
res5: Option[Int] = Some(3)

19

Das OptionObjekt verfügt über eine applyMethode, die genau das tut:

var myOptionalString = Option(session.get("foo"));

5

Beachten Sie, dass die Arbeit mit Java-Objekten nicht wie erwartet funktioniert:

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

1
Ich lief mit Scala 2.11.8. In der zweiten Zeile wurde NullPointerException ausgelöst. Die sechste Zeile hat Some (null), nicht None, wie Sie erwartet haben.
John Lin

1. Einige anstelle von Option in optionString verwendet - In der ursprünglichen Antwort geändert. 2. Nur in Scala 2.12.5
DekelM

-3

Dies ist ein sehr altes Thema, aber ein schönes!

Es ist wahr, dass das Konvertieren eines Nicht-Ausnahme-Ergebnisses von Try to Option zu einem ...

scala> Try(null).toOption
res10: Option[Null] = Some(null)

... weil es bei Try nicht um die Überprüfung der Nullfähigkeit geht, sondern nur um eine Möglichkeit, Ausnahmen funktional zu behandeln.

Wenn Sie versuchen, eine Ausnahme abzufangen, und diese zur Vereinfachung in eine Option konvertieren, wird Keine angezeigt, falls eine Ausnahme auftritt.

scala> Try(1/0).toOption
res11: Option[Int] = None

Sie möchten die Werte von Try beibehalten. Das kann null sein.

Aber es ist auch wahr, dass die Standardbibliothek manchmal ziemlich verwirrend ist ...

scala> Try(null).toOption
res12: Option[Null] = Some(null)

scala> Option(null)
res13: Option[Null] = None

Dieses Verhalten ist etwas inkonsistent, spiegelt jedoch die beabsichtigte Verwendung von Try und Option wider.

Sie verwenden try, um alles aus einem Ausdruck herauszuholen, der Ausnahmen auslösen kann, und die Ausnahme selbst ist Ihnen egal.

Der Wert, der herauskommen kann, kann sehr gut eine Null sein. Wenn toOption None gab, konnte man nicht zwischen einer Ausnahme und einer Null unterscheiden , und das ist nicht schön!

Standalone verwenden Sie Option, um die Existenz oder Nicht-Existenz von etwas zu kapseln. In diesem Fall ist Some (null) None, und das ist sinnvoll, da null in diesem Fall das Fehlen von etwas darstellt. Hier gibt es keine Mehrdeutigkeit.

Es ist wichtig zu beachten, dass die referenzielle Transparenz auf keinen Fall beeinträchtigt wird, da .toOption nicht mit Option () identisch ist.

Wenn Sie wirklich BEIDE Ausnahmesicherheit UND Nullsicherheit erzwingen müssen und Ihr Code wirklich nicht wirklich zwischen Null und einer Ausnahme unterscheiden muss , müssen Sie nur beide Paradigmen kombinieren! Denn genau das willst du, oder?

Sie können es auf eine Weise tun ...

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)

... oder ein anderes ...

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)

... oder der lächerlich hässlichste von ihnen ...

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)
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.