Scala Option (null) als Keine erwartet, aber ich habe einige (0)

9
val i: java.lang.Integer = null
val o: Option[Int] = Option(i) // This yields Some(0)

Was ist der sichere Weg, um null: java.lang.Integerzu Scala zu konvertieren Option[Int]?

anandhu sreekumar
quelle
1
Können Sie bitte Ihren Code in die Frage einfügen?
Виталий Олегович

Antworten:

17

Sie mischen Intund java.lang.Integerso

val i: java.lang.Integer = null
val o: Option[Int] = Option(i)

konvertiert implizit in

val o: Option[Int] = Option(Integer2int(i))

was wird

val o: Option[Int] = Option(null.asInstanceOf[Int])

somit

val o: Option[Int] = Some(0)

Wenn Sie mit arbeiten möchten java.lang.Integer, schreiben Sie

val o: Option[java.lang.Integer] = Option(i)
// o: Option[Integer] = None
Mario Galic
quelle
2
Dies wurde kürzlich irgendwo gefragt, also ist es ein echtes Problem. Vielleicht beruht das Problem auf Schlussfolgerungen: Option[Integer](i).map(_.intValue)scheint mir am idiomatischsten zu sein, da es sagt, was es tut. Verwenden Sie auch -Xlint, um die Warnung für die val o!
Som-Snytt
Um einen Box-Roundtrip zu vermeiden, wird `val x: Option [Int] = Option (i) .asInstanceOf [Option [Int]]` Integerabgeleitet.
Som-Snytt
7

Dies scheint zu geschehen, weil Sie das erstellen Optionund es Intin einem Schritt in ein konvertieren (die Antwort von @ MarioGalic erklärt, warum dies geschieht).

Das macht was du willst:

scala> val o: java.lang.Integer = null
o: Integer = null

scala> val i: Option[Int] = Option(o).map(_.toInt)
i: Option[Int] = None

scala> val o1: java.lang.Integer = 1
o1: Integer = 1

scala> val i1: Option[Int] = Option(o1).map(_.toInt)
i1: Option[Int] = Some(1)
Jack Leow
quelle
Auf die andere Antwort schlug ich vor _.intValue. Ich denke, es speichert nur den Conversion-Aufruf.
Som-Snytt
1

Konnte das gleiche Problem vor. Dieses fragwürdige Verhalten ist dem Scala-Team bekannt. Scheint, als würde eine Änderung etwas anderes zerstören. Siehe https://github.com/scala/bug/issues/11236 und https://github.com/scala/scala/pull/5176 .

Simpadjo
quelle
2
Das wirklich fragwürdige Verhalten wird nullals Ganzzahl behandelt. Dies ist vermutlich ein Kater, von Cdem aus es in Ordnung ist, 0einem Zeiger zuzuweisen . Dies bedeutet jedoch nicht, dass der resultierende Zeiger ist 0, so dass es zweifelhaft ist , auch in zwischen den beiden zu wechseln C.
Tim
IntegerHöchstwahrscheinlich stammt es aus Java-Code, daher ist "Null nicht als Ganzzahl behandeln" kein umsetzbarer Rat. Und wir überprüfen diese Ganzzahl explizit auf Nullfähigkeit mit Option.apply. Wir erhalten also eine unerwartete Ausgabe, ohne explizit unsichere Operationen auszuführen.
Simpadjo
Der Punkt ist, dass Sie Scala nicht für "fragwürdiges Verhalten" verantwortlich machen können, wenn die Hauptursache Java ist. Der umsetzbare Rat ist, eine explizite Konvertierung von Java-Typen in die entsprechenden Scala-Typen durchzuführen, anstatt eine implizite Konvertierung zu verwenden. (Daher JavaConverterseher als JavaConversion)
Tim
1
Nun, ich kann und ich beschuldige Scala, in diesem Fall keinen Kompilierungsfehler / keine Warnung ausgegeben zu haben. Sogar ein Laufzeitabsturz wäre besser. Selbst in meiner Firma haben 2 Entwickler mit mehr als 5 Jahren Erfahrung in Scala dieses Problem gelöst.
Simpadjo
1
@ Tim Es wäre sehr einfach, einen Laufzeitabsturz zu bekommen, indem man einfach anruft theInteger.intValue(). Das Vermeiden dieses Absturzes kostet eine zusätzliche Laufzeitprüfung. In älteren Versionen von Scala führte diese Konvertierung tatsächlich zu einer NPE. Es wurde als Fehler gemeldet und auf das aktuelle Verhalten behoben. Ich bin kein Scala-Experte, aber ich habe Scala-Dev # 355 und Scala # 5176 als historischen Kontext ausgegraben .
Amalloy