2013-08-15 14 views
41

Câu trả lời được chấp nhận cho this question mô tả cách tạo một phiên bản T trong lớp Generic<T>. Điều này liên quan đến việc truyền tham số Class<T> tới hàm tạo Generic và gọi phương thức newInstance từ đó.Làm cách nào để nhận thuộc tính `.class` từ thông số loại chung?

Một ví dụ mới của Generic<Bar> sau đó được tạo ra, và tham số Bar.class được thông qua vào.

Bạn làm gì nếu tham số kiểu chung chung cho các lớp mới Generic không phải là một số lớp tiếng như Bar nhưng bản thân nó là một loại thông số chung? Giả sử tôi có một số lớp khác Skeet<J> và tôi muốn tạo một cá thể mới là Generic<J> từ bên trong lớp đó. Sau đó, nếu tôi cố gắng vượt qua trong J.class Tôi nhận được lỗi trình biên dịch sau:

cannot select from a type variable. 

Có cách nào khác không?

Các bit cụ thể của mã kích hoạt các lỗi đối với tôi là:

public class InputField<W extends Component & WidgetInterface> 
               extends InputFieldArray<W> 
{ 
    public InputField(String labelText) 
    { 
    super(new String[] {labelText}, W.class); 
    } 
    /* ... */ 
} 

public class InputFieldArray<W extends Component & WidgetInterface> 
                   extends JPanel 
{ 
    /* ... */ 
    public InputFieldArray(String[] labelText, Class<W> clazz) 
          throws InstantiationException, IllegalAccessException 
    { 
    /* ... */ 

    for (int i = 0 ; i < labelText.length ; i++) { 
     newLabel = new JLabel(labelText[i]); 
     newWidget = clazz.newInstance(); 
     /* ... */ 
    } 
    /* ... */ 
    } 
    /* ... */ 
} 

Các lỗi xảy ra, bởi vì tôi không thể viết W.class. Có cách nào khác để vượt qua trong cùng một thông tin không?

+0

Câu hỏi của bạn có thể rõ ràng hơn nếu bạn viết mã ví dụ (tức là trình kích hoạt lỗi trình biên dịch). –

+0

Nhưng bạn phải có tên lớp trong 'Skeet 'phải không? Bạn cần phải chuyển lớp đó tới hàm tạo 'Generic'. Nếu bạn hiển thị mã thực tế, chúng tôi có thể giúp bạn tốt hơn. –

+0

bạn không thể sử dụng 'J.class' vì [type erasure] (http://stackoverflow.com/questions/tagged/type-erasure). Nhưng bạn có thể nhận được biến 'Class' cụ thể trên' Skeet 'xây dựng – RiaD

Trả lời

39

Sử dụng .class trên một số loại không được phép - vì type erasure, W sẽ đã xóa-Component khi chạy. InputField sẽ cũng cần phải mất một Class<W> từ người gọi, như InputFieldArray:

public InputField(String labelText, Class<W> clazz) 
{ 
    super(new String[] {labelText}, clazz); 
} 
+0

Căn cứ vào liên kết xóa loại đã cho, loại chung sẽ được thay thế bằng loại 'Đối tượng' vì không có ràng buộc nào được đưa ra trong trường hợp này. Vì vậy, vì kiểu 'Lớp' là lớp con của' Đối tượng', tôi nghĩ trong trường hợp này, chúng ta sẽ không thể gọi '.class'. Nhưng nếu ràng buộc nhất định không phải là 'Object' (như' ', tôi có nghĩa là phương thức' .class' vẫn nên được chọn trong trường hợp này. Tôi hơi bối rối ở đây. @Paul Bellora – Dreamer

+0

@Dreamer '.class' không phải là một phương thức hay bất cứ thứ gì có thể được giải quyết động trong thời gian chạy.Đây là một cấu trúc biên dịch được sử dụng để tĩnh nhận đối tượng' Class' biểu diễn một loại cụ thể rõ ràng. –

8

W có thể không có sẵn do loại tẩy xoá. Bạn nên yêu cầu một số Class<W> được chuyển vào phương thức. Bạn nhận được một đối tượng lớp và generic của nó đảm bảo rằng chỉ có W và không có lớp con nào được truyền vào, do hiệp phương sai.

public InputField(String labelText, Class<W> cls) 
{ 
    super(new String[] {labelText}, cls); 
} 

sẽ mất W.class nhưng không WSubtype.class.

1

tôi đã làm nó như thế này:

Đây là định nghĩa lớp của tôi:

public class ManagerGeneric <T> { 

Đây là trong phương pháp của tôi:

// Get the type of generic parameter 
Type typeOfT = new TypeToken<T>(){}.getType(); 
// Deserialize 
T data = gson.fromJson(json, typeOfT);