2015-06-02 18 views
8

Tôi đang cố gắng tìm ra lý do tại sao mã này không biên dịch trên JDK 1.8.0_45:Tại sao ví dụ dòng Java 8 này không biên dịch?

public class Example<E extends Example<E>> { 
    public List<? extends Example<?>> toExamples(Collection<String> collection) { 
     return collection.stream() 
       .map(v -> lookup(v)) 
       .collect(Collectors.toList()); 
    } 

    public static <E extends Example<E>> E lookup(String value) { 
     return null; 
    } 
} 

Thêm một dàn diễn viên dường như không cần thiết sửa chữa nó:

public class Example<E extends Example<E>> { 
    public List<? extends Example<?>> toExamples(Collection<String> collection) { 
     return collection.stream() 
       .map(v -> (Example<?>) lookup(v)) 
       .collect(Collectors.toList()); 
    } 

    public static <E extends Example<E>> E lookup(String value) { 
     return null; 
    } 
} 

Đây là lỗi từ trình biên dịch:

Example.java:9: error: incompatible types: inference variable R has incompatible bounds 
       .collect(Collectors.toList()); 
        ^
    equality constraints: List<Object> 
    upper bounds: List<? extends Example<?>>,Object 
where R,A,T are type-variables: 
    R extends Object declared in method <R,A>collect(Collector<? super T,A,R>) 
    A extends Object declared in method <R,A>collect(Collector<? super T,A,R>) 
    T extends Object declared in interface Stream 

Vì một lý do nào đó, loại trả về lookup() không được suy ra một cách chính xác cho việc mở rộng Example.

+1

tò mò, nó có biên dịch trên bất kỳ phiên bản Java 8 nào trước đây không? báo cáo này có vẻ rất liên quan: https://bugs.openjdk.java.net/browse/JDK-8077304 – EpicPandaForce

+0

Thông báo lỗi chính xác mà bạn nhận được là gì? – Jesper

+3

Bạn cũng có thể thay đổi chữ ký tra cứu: 'public static > Ví dụ tra cứu (giá trị chuỗi)' – assylias

Trả lời

8

Peter Lawrey pointed out, ? extends Example<?> không tương thích với E extends Example<E>. Tuy nhiên, ngay cả việc sửa chữ ký cũng không làm cho suy luận kiểu hoạt động ở đây.

Lý do là giới hạn đã biết của suy luận kiểu vì nó không truyền lại thông qua các lời gọi phương thức xích. Nói cách khác, kiểu trả về cho phép suy ra các kiểu cho lời gọi collect(…) nhưng không cho các lời gọi map(…) trước đó. (Xem thêm this answer)

Nhưng nó hoạt động cho lồng nhau lời gọi phương pháp, vì vậy phương pháp viết lại sau đây có thể được biên dịch:

public class Example<E extends Example<E>> { 
    public <E extends Example<E>> List<E> toExamples(Collection<String> collection) { 
     return collection.stream() 
      .collect(Collectors.mapping(v -> lookup(v), Collectors.toList())); 
    } 

    public static <E extends Example<E>> E lookup(String value) { 
     return null; 
    } 
} 

Tuy nhiên, bạn cần phải suy nghĩ lại về ngữ nghĩa của mã của bạn. Tham số loại của phương thức chỉ xuất hiện ở loại trả về không thể chính xác vì nó ngụ ý rằng “bất kỳ người gọi nào thay thế cho tham số loại này, phương thức sẽ trả về điều đúng”. Vì việc triển khai phương thức không biết người gọi giả định điều gì, điều này là không thể. Chỉ trả lại null hoặc danh sách trống sẽ hoạt động chính xác, ít được sử dụng.

+0

Cảm ơn, tôi đã có thể sửa nó theo cách này. Lưu ý rằng vấn đề thực tế đã có một 'Lớp > 'tham số trong phương thức' toExamples() 'và tham số' Class 'trong phương thức' lookup() '. Vì vậy, tôi sợ tôi đã giải thích được vấn đề. –

+1

Sau đó, với một tham số đầu vào kiểu 'Class ' mà bạn đi qua, suy luận kiểu cũng nên làm việc với một lời gọi '.map (…) .collect (…)' bị xích. – Holger

1

Đoán của tôi là kiểu chung được xác định trong phương thức tĩnh không giống với kiểu generic được định nghĩa trong lớp. Bạn sẽ có thể để làm cho lookup phương pháp tĩnh không để nó phù hợp với cùng loại quy định tại tờ khai chung cấp lớp:

public E lookup(String value) { 
     return null; 
    } 
7

Khi bạn có một ? nó không bình đẳng khác ? tức là trình biên dịch doesn' t thấy

? extends Example<?> 

làm kết hợp cho

E extends Example<E> 

vì nó không thể giả định hai ? là sa tôi. Có thể là

A extends Example<B> 

Khi bạn thực hiện diễn viên, bạn che khuất ràng buộc để nó có thể khớp.

Các vấn đề liên quan