2017-11-20 20 views
7

Tôi đang sử dụng Java 1.8.0_151 và có một số mã mà không biên dịch và tôi không hiểu:Java8 generic đố

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 

lý do tại sao nó hoạt động tốt trên result1 nhưng cho lỗi biên dịch trên result3 ?
Thông tin thêm:

  • Trong dòng đầu tiên, khi tôi thay đổi Optional-Optional<String>, result3 cũng có thể biên dịch
  • Khi tôi phá vỡ result3 thành 2 dòng: như result1result2, result3 có khả năng biên dịch
+4

Bản sao có thể có của [Loại thô là gì và tại sao chúng ta không nên sử dụng?] (Https://stackoverflow.com/questions/2770321/what-is-a-raw-type-and-why-shouldnt -we-use-it) – Andrew

+2

@AndrewTobilko có thể là OP đã làm * với mục đích * – Eugene

Trả lời

0

Cám ơn câu trả lời của bạn. Tôi chỉ muốn cung cấp chi tiết về lý do tại sao nó làm việc trên resutl1 nhưng không result3 trên:

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 

trên result1, biến optional là kiểu thô, vì vậy optional.map(obj -> true) trả lại một kiểu thô Optional.

Khi tôi tuyên bố Optional<Boolean> result1, Optional loại thô đã tự động đúc-Optional<Boolean>
Mặt khác, optional.map(obj -> true).orElse(false); thất bại vì một kiểu thô Optional đối tượng không thể gọi .orElse(false)

Một ví dụ về hành vi này với loại nguyên liệu là :

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()); 

sẽ hoạt động tốt cho mọi trường hợp, đối tượng li wi sẽ chứa một String, một số nguyên và một HashMap(). li1, li2, li3 được tự động truyền sang loại không phải thô.

4

optional là một nguyên Optional, vì vậy optional.map(obj -> true) trả về một nguyên Optional, và orElse(false) lợi nhuận an Object, không phải là Boolean. Trình biên dịch không biết cách bỏ chọn một ô Object thành boolean.

Bằng cách thay đổi

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

để

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

hoặc

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

bạn sẽ vượt qua lỗi này, kể từ bây giờ optional.map(obj -> true) sẽ trả về một Optional<Boolean>orElse(false) sẽ trả về một Boolean.

+0

Tôi sợ 'optional.map (obj -> true);' không trả lại một raw 'Optional', nhưng' Tùy chọn ' bởi vì dòng: 'Tùy chọn result1 = optional.map (obj -> true);' hoạt động tốt – HenryNguyen

+3

@Henry thực sự là một loại thô có thể được gán.cho một loại chung, do đó nhiệm vụ không có nghĩa là những gì bạn nghĩ nó có. – Eran

+0

ohhhhhh wow Tôi không biết điều đó, cảm ơn! – HenryNguyen

8

Khi bạn mất an toàn loại - nó sẽ bị mất cho các cuộc gọi bị xích là tốt. Đó là Optional<Object> != Optional. Vì vậy, khi bạn làm

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

Các map chỉ có thể chấp nhận một nguyên Function và không có gì khác, mà sẽ trả về một Object rõ ràng.

Cách đúng là để thêm thông tin loại:

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

Hoặc bạn có thể cast không an toàn:

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