2017-07-03 14 views
14

Tại sao đoạn mã dưới đây biên dịch? OtherInterface không mở rộng Concrete vì vậy tôi sẽ đặt cược một quả thận rằng điều này sẽ không biên dịch. Nhưng nó có.Vi phạm loại hiển nhiên, nhưng biên dịch

public class Test { 

    public static interface SomeInterface {} 

    public static interface OtherInterface{} 

    public static class Concrete implements SomeInterface { 

     public <T extends Concrete> T getConcrete() { 
      return null; 
     } 
    } 

    public static void doStuff() { 
     Concrete c = new Concrete(); 
     OtherInterface iCompile = c.getConcrete(); 
    } 
} 

Mặt khác, đoạn mã tiếp theo không biên dịch, đó là những gì tôi mong đợi.

public class Test { 

    public static interface SomeInterface {} 

    public static class UnrelatedClass{} 

    public static class Concrete implements SomeInterface { 

     public <T extends Concrete> T getConcrete() { 
      return null; 
     } 
    } 

    public static void doStuff() { 
     Concrete c = new Concrete(); 
     UnrelatedClass iCompile = c.getConcrete(); 
    } 
} 
+0

@azurefrog Điều thứ hai không biên dịch cho tôi (tôi không phải OP) và thông báo lỗi là anh ta gửi về 'T' (là' Concrete') không khớp với 'UnrelatedClass'. – Tom

+0

@azurefrog, nhận xét của Tom là những gì tôi có – Jerome

+2

Trình biên dịch có thể giống như trong câu hỏi này: https://stackoverflow.com/questions/29670018/why-can-this-generic-method-with-a- bound-return-any-type. Trình biên dịch gây ra một kiểu giao cắt 'Concrete & OtherInterface'. – Radiodef

Trả lời

5

Sự khác biệt là ở đây:

public static interface OtherInterface{} ... 
OtherInterface iCompile = c.getConcrete(); 

vs

public static class UnrelatedClass{} ... 
UnrelatedClass iCompile = c.getConcrete(); 

Ý nghĩa: trong trường hợp đầu tiên, bạn gọi phương thức để trở về một thể hiện của một số giao diện. Giao diện có thể là mọi lớp.

Trong ví dụ thứ hai, bạn hướng dẫn loại trả về là lớp cụ thể! Một lớp được biết đến và rằng không triển khai giao diện khác đó!

Và thông báo lỗi:

lý do: không có trường hợp tối đa duy nhất tồn tại cho loại T biến với giới hạn trên UnrelatedClass, bê tông

là khá cụ thể ở đây.

Nói cách khác: các yếu tố trình biên dịch ở phía bên trái của nhiệm vụ đó - để xác định các loại hợp lệ. Và UnrelatedClass có thể không bao giờConcrete - bởi vì lớp UnrelatedClass không không mở rộng Concrete!

Trong khi đó, cái gì đó là SomeInterface cũng có thể cũng như triển khai OtherInterface.

+1

Bạn đang giải thích lý do đoạn trích thứ hai không biên dịch, điều này tốt, nhưng tôi đã biết điều đó. Nó không thực sự giải thích lý do tại sao người đầu tiên mặc dù. nếu 'getConcrete()' không phải là generic và trả về Concrete, đoạn đầu tiên sẽ không biên dịch. – Jerome

+1

Huh? Ví dụ đầu tiên trả về một thể hiện của một số giao diện. Lớp thực tế không xác định và có thể triển khai thực hiện giao diện khác đó. – GhostCat

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