2011-12-18 24 views
10

Tôi đã thử nghiệm một số thứ với các tham số bị chặn trong các phương thức chung và tôi đã phát hiện một số hành vi lạ.
Sẽ thật tuyệt nếu có ai đó có thể giải thích hai lỗi trong đoạn mã sau.Các thông số giới hạn Java trong các phương thức chung

Hãy tưởng tượng có hai lớp học Class1Class2 cả hai mở rộng từ BaseClass. Class2 triển khai Giao diện.

Trong Class1, tôi có một phương pháp mà trả về một thể hiện của Class2 theo cách sau:

public class Class2 extends BaseClass implements Interface { 

    @Override 
    public void method() { 
     System.out.println("test"); //$NON-NLS-1$ 
    } 
} 

public class Class1 extends BaseClass { 

    public <T extends BaseClass & Interface> T getTwo() { 
     return new Class2(); 
     // Error: Type mismatch: cannot convert from Class2 to T 
    } 

    public static void main(String[] args) { 
     Interface two = new Class1().getTwo(); 
     // Error: Bound mismatch: The generic method getTwo() of type Class1 is 
     // not applicable for the arguments(). The inferred type Interface is 
     // not a valid substitute for the bounded parameter <T extends BaseClass 
     // & Interface> 
     System.out.println(two); 
    } 
} 
+0

Nó có vẻ như lạm dụng thuốc generic. Trên thực tế 'getTwo' phải có kiểu trả về chỉ' Class2', hoặc 'BaseClass', hoặc' Interface'. Nếu 'T' được định nghĩa chỉ cho một phương thức thì không có cách nào để trình biên dịch biết lớp nào chính xác thay thế' T' tại dòng 'new Class1(). GetTwo()'. Sẽ chỉ có thể nếu 'getTwo' có các tham số đầu vào của kiểu này. – DRCB

Trả lời

5

Các lỗi tổng hợp đầu tiên xảy ra bởi vì các thông số kiểu được khai báo bằng các phương pháp được quy định bởi người gọi, không phải là thực hiện phương pháp . Đó là, cho

class Class3 extends BaseClass implements Interface { ... } 

một người gọi có thể viết

Class3 c3 = new Class1().<Class3>getTwo(); 

, nhưng việc thực hiện phương thức trả về một Class2, mà không phải là một subtype của T = Class3.

Lỗi biên dịch thứ hai xảy ra vì các tham số kiểu không được chỉ định rõ ràng bởi người gọi được suy ra từ các đối số phương thức và kiểu biến mà giá trị trả về của phương thức được gán cho. Suy luận này không thành công ở đây. Cách giải quyết thông thường, được đề xuất bởi Đặc tả Ngôn ngữ Java, là chỉ rõ các tham số kiểu một cách rõ ràng trong các trường hợp như vậy (suy luận kiểu được dùng để thuận tiện cho các trường hợp đơn giản; nó không nhằm che giấu tất cả các trường hợp).

Đối với cách khai báo đúng thông số loại này, tôi cần biết bạn đang cố gắng làm gì với các khai báo này.

+1

+1 Câu trả lời hay. Tôi nghĩ cú pháp sẽ là 'new Class1(). getTwo() 'trong ví dụ mã thứ hai của bạn. –

+0

Ồ, tất nhiên rồi. Cảm ơn, cố định. – meriton

+0

Tôi thấy điểm cho lỗi biên dịch đầu tiên, nhưng tôi không chắc chắn về điều thứ hai. Cuộc gọi 'BaseClass two = new Class1(). GetTwo();' có vẻ như là ok trên hệ thống của tôi nhưng không thành công trên hệ thống của đồng nghiệp và gọi 'Giao diện hai = new Class1(). GetTwo();' không thành công hệ thống của tôi cũng vậy (như đã trình bày ở trên) ... – Marco

4

Tại sao nên sử dụng Generics cho phương pháp getTwo, khi bạn biết đó là Class2? Đơn giản chỉ cần làm điều này:

public Class2 getTwo() { 
    return new Class2(); 
} 

Nếu bạn đang trọng một phương pháp public <T extends BaseClass & Interface> T getTwo(), trình biên dịch sẽ cho phép bạn khai báo impl của bạn như public Class2 getTwo() khi bạn T cho impl của bạn là Class2

+0

Không ghi đè nhanh quá mức đó. Trong kịch bản của bạn, bạn sẽ ghi đè một phương thức có thể trả về bất kỳ T thỏa mãn ràng buộc nào với phương thức trả về Class2, điều này không được phép vì cùng một lý do mã OP không được phép. Tôi không chắc chắn Java thậm chí có thể thể hiện một loại trả về với một định lượng tồn tại. –

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