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]?


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

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)

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 .


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
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.