2017-11-20 154 views
7

Używam Java 1.8.0_151 i tam jest jakiś kod, który nie sporządza i nie rozumiem:Java8 generic puzzle

Optional optional = Optional.of("dummy"); 
Optional<Boolean> result1 = optional.map(obj -> true);  // works fine 
boolean result2 = result1.orElse(false);     // works fine 
boolean result3 = optional.map(obj -> true).orElse(false); // compilation error: Incompatible types: required boolean, found object 
Object result4 = optional.map(obj -> true).orElse(false); // works fine 

dlaczego to działa dobrze na result1 ale daje błąd kompilacji na result3 ?
Dodatkowe informacje:

  • W pierwszej linii, kiedy zmienić Optional do Optional<String>, result3 jest również w stanie skompilować
  • Kiedy złamię result3 na 2 linie: jak result1 i result2, result3 jest w stanie skompilować
+4

Możliwy duplikat [Co to jest typ surowy i dlaczego nie powinniśmy go używać?] (Https://stackoverflow.com/questions/2770321/what-is-a-raw-type-and-why-shouldnt -we-use-it) – Andrew

+2

@AndrewTobilko może być OP zrobił to * celowo * – Eugene

Odpowiedz

0

Dzięki za odpowiedzi. Chcę tylko, aby podać szczegóły na temat dlaczego to działało na resutl1 ale nie result3 na:

Optional<Boolean> result1 = optional.map(obj -> true);  // works fine 
boolean result2 = result1.orElse(false);     // works fine 
boolean result3 = optional.map(obj -> true).orElse(false); // compilation error: Incompatible types: required boolean, found object 

na result1, zmienna optional był rodzaj surowca, tak optional.map(obj -> true) zwrócił Optional typu RAW.

Gdy oświadczyłem Optional<Boolean> result1, Optional typ surowy był automatycznie lanego do Optional<Boolean>
Z drugiej strony, optional.map(obj -> true).orElse(false); powiodła się, ponieważ rodzaj surowego Optional obiekt nie może zadzwonić .orElse(false)

Innym przykładem takiego zachowania z surowego typu jest :

List li = new ArrayList<String>(); 
List<String> li1 = li; 
List<Integer> li2 = li; 
List<Map> li3 = li; 

li1.add("WWW"); 
li2.add(444); 
li3.add(new HashMap()); 

będzie działać dobrze dla wszystkich scenariuszy, Wi li obiektu ll zawierać ciąg, Integer i HashMap(). Model li1, li2, li3 został automatycznie rzucony do typu nie-surowego.

4

optional jest surowy Optional, więc optional.map(obj -> true) zwraca surowe Optional i orElse(false) powraca Object, a nie Boolean. Kompilator nie wie, jak odłączyć urządzenie od Object do boolean.

Zmieniając

Optional optional = Optional.of("dummy"); 

do

Optional<Object> optional = Optional.of("dummy"); 

lub

Optional<String> optional = Optional.of("dummy"); 

będzie przezwyciężyć ten problem, ponieważ teraz optional.map(obj -> true) zwróci Optional<Boolean> i orElse(false) zwróci Boolean.

+0

Boję się 'optional.map (obj -> true);' nie zwraca surowego 'Opcjonalnie', ale' Opcjonalnie ' ponieważ linia: 'Opcjonalnie result1 = optional.map (obj -> true);' działa dobrze – HenryNguyen

+3

@Henry faktycznie typ surowy może być przypisany.do typu ogólnego, tak, że przydział nie oznacza, co myślisz to robi. – Eran

+0

ohhhhhh wow, nie wiedziałem o tym, dzięki! – HenryNguyen

8

Po utracie bezpieczeństwa typu - jest on tracony dla połączeń połączonych, jak również. To jest Optional<Object> != Optional. Więc kiedy zrobić

Optional optional = Optional.of("dummy"); 
optional.map() 

map może jedynie zaakceptować surowego Function i nic poza tym, co zwróci Object oczywiście.

Prawidłowe sposobem jest dodanie informacji typu:

Optional<String> optional = Optional.of("dummy"); 

Albo można oddać niebezpieczny:

boolean result3 = (boolean) optional.map(obj -> true).orElse(false)