2011-12-28 38 views
8

Tôi nghĩ rằng điều này có thể liên quan đến Why does a generic cast of a List<? extends Set..> to List<Set..> succeed on Sun JDK 6 but fail to compile on Oracle JDK 7?Loại suy luận hạn chế hơn trong JDK 7 so với JDK 6?

Nếu chúng ta lấy các lớp sau, họ biên dịch tốt dưới JDK 6:

public final class Foo<V> { 

    private final V value; 

    private Foo(final V value) { 

     this.value = value; 
    } 

    public static <T, R extends T> Foo<T> of(final R value) { 

     return new Foo<T>(value); 
    } 
} 

final class Tester { 

    @Test(groups="unit") 

    public static void test() { 

     bar(Foo.of(BigDecimal.ZERO)); // This line fails in JDK 7 but not JDK 6 
    } 

    private static void bar(final Foo<? extends Number> target) { 

     assert target != null; 
    } 
} 

Tuy nhiên, theo JDK 7, tôi nhận được lỗi sau:

[ERROR] \work\fsb-core\src\test\java\com\fsb\core\Foo.java:[42,8] error: 
       method bar in class Tester cannot be applied to given types; 

Tôi nghĩ suy luận kiểu ít hạn chế hơn (ví dụ, thêm suy đoán hàm tạo) trong JDK 7. Tuy nhiên, ở đây, trình biên dịch đang từ chối một loại có giá trị theo JDK 6.

Đây có phải là lỗi không? Hoặc là các quy tắc về suy luận được thực hiện nghiêm ngặt hơn cho các phương pháp?

+0

Java 8 (1.8.0_25) điều này biên dịch lại tốt. – Lii

Trả lời

3

Theo đúng thông số, T không thể suy ra (mỗi ngày 15.12.2.7), vì vậy cần được xem là Object.

Điều này có thể được xem là lỗi của thông số kỹ thuật. Đây là cách thông số kỹ thuật infers R: đầu tiên có ràng buộc R :> BigDecimal, trong đó :> có nghĩa là là siêu kiểu của. Các quy tắc suy luận sau đó chọn R=BigDecimal vì đây là loại cụ thể nhất thỏa mãn ràng buộc.

Bây giờ, kể từ T:>R, T:>BigDecimal, người ta nghĩ điều này cũng sẽ mang lại T=BigDecimal.

Rất tiếc, các quy tắc suy luận không tính T:>R vào tài khoản. Không có sự ràng buộc nào trên T. T không được phỏng đoán thông qua cùng một nguyên tắc.

Trong khi hút, thông số kỹ thuật là thông số kỹ thuật. Mã của bạn không được biên dịch. Javac6 là sai ở đó.

Trong Java 8, có một cải tiến lớn về các quy tắc suy luận để làm cho biểu thức lambda dễ sử dụng hơn. Hy vọng rằng mã của bạn nên biên dịch trong Java 8.

+0

Cảm ơn bạn đã giải thích. Tôi cảm thấy nhẹ nhõm khi suy luận kiểu là đúng trong JDK 7 (tho đôi chút chán nản nó chỉ làm việc vô tình trong JDK 6). Có vẻ như điều này liên quan đến: http://www.oracle.com/technetwork/java/javase/compatibility-417013.html. (Tham chiếu ban đầu tại http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6638712). – Saish

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