Niedawno gdzieś o to pytano, więc to prawdziwa gotcha. Być może problem polega na wnioskowaniu: Option[Integer](i).map(_.intValue)wydaje mi się najbardziej idiomatyczny, ponieważ mówi, co robi. Użyj także, -Xlintaby zobaczyć ostrzeżenie dla val o!
To wydaje się dzieje dlatego, że tworzenie Optioni przekształcenie go do Intw jednym kroku (@ MarioGalic za odpowiedź wyjaśnia, dlaczego tak się dzieje).
Naprawdę wątpliwe zachowanie traktuje się nulljako liczbę całkowitą. Jest to prawdopodobnie kac, z Cktórego można przypisać 0wskaźnik. Ale to nie znaczy, że wynikowy wskaźnik jest 0taki, więc przełączanie się między nimi jest niejasne C.
Tim
Integernajprawdopodobniej pochodzi z kodu Java, więc „nie traktuj wartości null jako liczby całkowitej” nie jest praktyczną radą. I jawnie sprawdzamy tę liczbę całkowitą pod kątem używania zerowalności Option.apply. Otrzymujemy więc nieoczekiwany wynik bez jawnego wykonywania niebezpiecznych operacji.
simpadjo
Chodzi o to, że nie można winić Scali za „wątpliwe zachowanie”, gdy główną przyczyną jest Java. Poradą praktyczną jest jawna konwersja z typów Java na równoważne typy Scala zamiast korzystania z niejawnej konwersji. (Stąd JavaConvertersraczej niż JavaConversion)
Tim
1
Cóż, mogę i obwiniam Scalę za to, że w tym przypadku nie wyemitował błędu kompilacji / ostrzeżenia. Nawet awaria środowiska uruchomieniowego byłaby lepsza. Nawet w mojej samej firmie 2 programistów z ponad 5-letnim doświadczeniem w Scali dotknęło tego problemu.
simpadjo
1
@Tim Bardzo łatwo byłoby uzyskać awarię środowiska wykonawczego, po prostu dzwoniąc theInteger.intValue(). Uniknięcie tej awarii kosztuje dodatkowe sprawdzenie środowiska wykonawczego. W starszych wersjach Scali ta konwersja rzeczywiście spowodowała powstanie NPE; został zgłoszony jako błąd i naprawiony do bieżącego zachowania. Nie jestem ekspertem Scala, ale wykopałem scala-dev # 355 i scala # 5176 jako kontekst historyczny.
Odpowiedzi:
Mieszacie
Int
ijava.lang.Integer
tak dalejpośrednio konwertuje na
który staje się
a zatem
Jeśli chcesz pracować
java.lang.Integer
, napiszźródło
Option[Integer](i).map(_.intValue)
wydaje mi się najbardziej idiomatyczny, ponieważ mówi, co robi. Użyj także,-Xlint
aby zobaczyć ostrzeżenie dlaval o
!Integer
wywnioskowano `val x: Opcja [Int] = Opcja (i) .asInstanceOf [Opcja [Int]]`To wydaje się dzieje dlatego, że tworzenie
Option
i przekształcenie go doInt
w jednym kroku (@ MarioGalic za odpowiedź wyjaśnia, dlaczego tak się dzieje).Robi to, co chcesz:
źródło
_.intValue
. Wydaje mi się, że zapisuje tylko konwersję.Wcześniej ten sam problem. To wątpliwe zachowanie jest znane zespołowi Scali. Wygląda na to, że zmiana go psuje coś innego. Zobacz https://github.com/scala/bug/issues/11236 i https://github.com/scala/scala/pull/5176 .
źródło
null
jako liczbę całkowitą. Jest to prawdopodobnie kac, zC
którego można przypisać0
wskaźnik. Ale to nie znaczy, że wynikowy wskaźnik jest0
taki, więc przełączanie się między nimi jest niejasneC
.Integer
najprawdopodobniej pochodzi z kodu Java, więc „nie traktuj wartości null jako liczby całkowitej” nie jest praktyczną radą. I jawnie sprawdzamy tę liczbę całkowitą pod kątem używania zerowalnościOption.apply
. Otrzymujemy więc nieoczekiwany wynik bez jawnego wykonywania niebezpiecznych operacji.JavaConverters
raczej niżJavaConversion
)theInteger.intValue()
. Uniknięcie tej awarii kosztuje dodatkowe sprawdzenie środowiska wykonawczego. W starszych wersjach Scali ta konwersja rzeczywiście spowodowała powstanie NPE; został zgłoszony jako błąd i naprawiony do bieżącego zachowania. Nie jestem ekspertem Scala, ale wykopałem scala-dev # 355 i scala # 5176 jako kontekst historyczny.