2013-03-31 27 views
6

Tôi không hiểu tại sao điều này confuses trình biên dịch. Tôi đang sử dụng chung loại T để giữ một đối tượng mà không liên quan đến các putget phương pháp. Tôi luôn nghĩ rằng GenericClassGenericClass<Object> có chức năng giống hệt nhau, nhưng tôi phải nhầm lẫn. Khi biên soạn lớp DoesntWork tôi nhận được incompatible types - required: String - found: Object. Lớp Works làm những gì tôi mong đợi. Những gì đang xảy ra ở đây?Tại sao lớp này hoạt động khác khi tôi không cung cấp loại chung?

public class GenericClass<T> { 
    public <V> void put(Class<V> key, V value) { 
     // put into map 
    } 

    public <V> V get(Class<V> key) { 
     // get from map 
     return null; 
    } 

    public static class DoesntWork { 
     public DoesntWork() { 
      GenericClass genericClass = new GenericClass(); 
      String s = genericClass.get(String.class); 
     } 
    } 

    public static class Works { 
     public Works() { 
      GenericClass<Object> genericClass = new GenericClass<Object>(); 
      String s = genericClass.get(String.class); 
     } 
    } 
} 
+0

'genericClass' gần với' genericClass 'hơn là' genericClass ' –

+0

Điều đó đang được nói, tôi không thể thấy tại sao' DoesntWork' không hoạt động. –

+1

Hãy thử buộc loại: 'genericClass. nhận được (String.class) '(không chắc chắn đó là đúng cú pháp) –

Trả lời

8

Những điều về cách loại thô làm việc - kiểu generic mà bạn đã bỏ qua các đối số cho - đó là tất cả Generics cho họ và phương pháp của họ được xoá hoàn toàn là tốt. Vì vậy, đối với một nguyên GenericClass, các getput phương pháp cũng mất Generics của họ.

+0

Tại sao họ? –

+0

Việc sử dụng các loại thô, về cơ bản, là dấu hiệu cho biết bạn đang sử dụng mã cũ, tiền Generics, vì mục đích tương thích; hầu hết các tính năng kỳ lạ xung quanh các loại thô đều có tính năng tương thích. [JLS 4.8] (http://docs.oracle.com/javase/specs/jls/se7/html/jls-4.html#jls-4.8) có thêm chi tiết. –

+2

Nhưng đối với một ví dụ về lý do tại sao hành vi cụ thể này là cần thiết, hãy xem xét ví dụ sau: mã kế thừa được tạo bằng Java 1.4 phải có cùng hành vi từ 'Danh sách' từ Java 1.4 - tiền Generics - và từ' List' từ Java 5, được viết lại để giới thiệu Generics. Nó khó xử, nhưng cần thiết cho khả năng tương thích ngược - nhưng nó không bao giờ là vấn đề đối với mã mới, vì mã mới về cơ bản không bao giờ nên sử dụng các kiểu thô. –

1

Điều này là do khi bạn làm việc với một lớp chung mà không có loại thông tin thêm bạn làm việc với những gì đôi khi được gọi là hình thức degenerate của lớp. Biểu mẫu degenerate có TẤT CẢ thông tin loại chung được loại bỏ.

Về cơ bản - lớp học của bạn trở thành một cái gì đó như:

hành vi
public class GenericClass { 
    public void put(Class key, Object value) { 
     // put into map 
    } 

    public Object get(Class key) { 
     // get from map 
     return null; 
    } 

    ... 
} 

Câu trả lời biên dịch bạn đang nhìn thấy được vì vậy mong đợi.

Nó đề cập trong một Java Puzzlers.

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