2015-04-17 22 views
11

Các mã sau đây hoạt động khi biên soạn với sourceCompatibility = 1,7 hoặc 1,6, nhưng thất bại sau khi chuyển sang 1.8:Tại sao mã này thất bại với sourceCompatibility = 1,8

public class Java8Wat { 
    interface Parcelable { 
    } 

    static class Bundle implements Parcelable { 
    public void put(Parcelable parcelable) { 
    } 

    public void put(Serializable serializable) { 
    } 

    public <T extends Parcelable> T getParcelable() { 
     return null; 
    } 
    } 

    static { 
    Bundle inBundle = new Bundle(); 
    Bundle outBundle = new Bundle(); 

    outBundle.put(inBundle.getParcelable()); 
    } 
} 

Compilation đầu ra:

Java8Wat.java:23: error: reference to put is ambiguous 
     outBundle.put(inBundle.getParcelable()); 
      ^
both method put(Parcelable) in Bundle and method put(Serializable) in Bundle match 

Dưới đây là mã repo có mã lỗi: https://github.com/chalup/java8-wat. Chỉ cần gọi ./gradlew clean build từ thư mục dự án.

Tôi lướt qua JLS cho Java 8, nhưng tôi chưa tìm thấy bất kỳ điều gì có liên quan.

quan sát khác: mã biên dịch nếu tôi thay đổi chữ ký getParcelable() tới:

public Parcelable getParcelable() 

Tại sao biên dịch java coi put(Serializable) là phương pháp có khả năng áp dụng cho outBundle.put(inBundle.getParcelable()) cuộc gọi và những thay đổi cần được thực hiện để lớp Parcelable/Bundle ? Câu hỏi bổ sung: tại sao lỗi này chỉ xảy ra trên Java 8 chứ không phải trên Java 7?

+0

Liên quan: [Phương pháp mơ hồ trong Java 8, tại sao?] (Http://stackoverflow.com/questions/29499847/ambiguous-method-in-java-8-why) –

+0

Tôi sẽ đăng câu trả lời. Oh well. ; p – Radiodef

Trả lời

3

tôi sẽ đề nghị rằng đây là do sự thay đổi trong cách suy luận được thực hiện trong java 8. Và thực tế là Parcelable là một giao diện. Vì lý do này, kiểu trả về được yêu cầu là getParcelable dẫn đến một cuộc gọi không rõ ràng vì loại trả về suy luận có thể được áp dụng cho cả hai phương pháp.

tôi chủ yếu sẽ đề cập đến câu hỏi này khác với một lời giải thích rõ ràng hơn: Why can this generic method with a bound return any type?

Tính đến sự hiểu biết thực sự của cách suy luận làm việc trong trường hợp cụ thể này và tại sao nó lại khác nhau giữa java 7 và 8, điều này sẽ yêu cầu nghiên cứu sâu hơn về số inference part của JLS.

+1

Nó hoạt động trong Java 7 vì Java 7 chỉ các đối số kiểu suy luận dựa trên một mục tiêu trả về nếu nó phải chịu chuyển đổi chuyển nhượng. Nếu không thì giới hạn trên được suy ra. Nói cách khác, thực tế là một trong những cuộc gọi là bên trong khác như 'f (g());' là lý do tại sao có một sự khác biệt. Trong Java 7, 'put (Serializable)' không thể áp dụng theo cách này. – Radiodef

1

Khi thông báo cho biết reference to put is ambiguous.

Bạn phải explizity đúc giá trị để trình biên dịch biết phương pháp Mà bạn muốn sử dụng:

outBundle.put((Parcelable)Bundle.getParcelable()); 

hoặc

outBundle.put((Serializable)Bundle.getParcelable()); 
+0

Đó là một cách giải quyết, nhưng điều tôi muốn biết là tại sao trình biên dịch giả định rằng kiểu trả về của 'getParcelable' là' Serializable', dẫn đến sự mơ hồ. – chalup

+1

nhưng tại sao có sự khác biệt giữa java 8 và trước đó? – eis

+2

Câu trả lời này chỉ giải quyết một phần của hai (hoặc ba) phần câu hỏi. – Vulcan

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