2011-01-29 37 views
63

Tôi nhận được một danh sách, được lập trình như sau: public class MyList<T>. Có cách nào để sử dụng biến T để có được tên của lớp (vì vậy tôi có thể, từ bên trong MyList, biết nếu T là String, Socket, vv)?Generics Java - tham gia lớp học?

EDIT: Không bao giờ, tìm thấy câu trả lời here.

+0

Bạn biết câu trả lời đã có, nhưng bạn có thể muốn xem http://google-guice.googlecode.com/svn/trunk/javadoc/com/google/inject/TypeLiteral.html – maaartinus

Trả lời

89

Câu trả lời ngắn: Bạn không thể.

Long trả lời:

Do cách Generics được thực hiện trong Java, loại T generic không được giữ lại khi chạy. Tuy nhiên, bạn có thể sử dụng thành viên dữ liệu cá nhân:

public class Foo<T> 
{ 
    private Class<T> type; 

    public Foo(Class<T> type) { this.type = type; } 
} 
24

Bạn đang thấy kết quả của Type Erasure. Từ trang đó ...

Khi một kiểu generic được khởi tạo, trình biên dịch chuyển những loại bởi một kỹ thuật gọi là loại tẩy xoá - một quá trình nơi trình biên dịch loại bỏ tất cả thông tin liên quan đến gõ thông số và loại đối số trong một lớp hoặc phương thức . Kiểu xóa cho phép các ứng dụng Java sử dụng generics để duy trì khả năng tương thích nhị phân với Các thư viện và ứng dụng Java mà được tạo trước khi dùng chung.

Ví dụ, Hộp < Chuỗi > là dịch sang gõ Box, đó là gọi là kiểu thô - một kiểu thô là một lớp generic hoặc giao diện tên mà không cần bất kỳ đối số kiểu. Điều này có nghĩa là mà bạn không thể tìm ra loại Đối tượng lớp chung nào đang sử dụng tại thời gian chạy là .

Điều này cũng giống như thế này questionpretty good answer as well.

3

Tôi không chắc chắn 100% nếu điều này làm việc trong mọi trường hợp (cần ít nhất Java 1.5):

import java.lang.reflect.Field; 
import java.lang.reflect.ParameterizedType; 
import java.lang.reflect.Type; 
import java.util.HashMap; 
import java.util.Map; 

public class Main 
{ 
    public class A 
    { 
    } 

    public class B extends A 
    {  
    } 


    public Map<A, B> map = new HashMap<Main.A, Main.B>(); 

    public static void main(String[] args) 
    { 

     try 
     { 
      Field field = Main.class.getField("map");   
      System.out.println("Field " + field.getName() + " is of type " + field.getType().getSimpleName()); 

      Type genericType = field.getGenericType(); 

      if(genericType instanceof ParameterizedType) 
      { 
       ParameterizedType type = (ParameterizedType) genericType;    
       Type[] typeArguments = type.getActualTypeArguments(); 

       for(Type typeArgument : typeArguments) 
       { 
        Class<?> classType = ((Class<?>)typeArgument);     
        System.out.println("Field " + field.getName() + " has a parameterized type of " + classType.getSimpleName()); 
       } 
      } 
     } 
     catch(Exception e) 
     { 
      e.printStackTrace(); 
     } 
    }  
} 

Sản lượng này sẽ:

đồ Field là loại đồ
đồ Dòng có một kiểu tham số của A đồ
Dòng có một kiểu tham số của B

+0

Một khi tôi đã cố gắng để làm tương tự trong quá trình tái cấu trúc của Tổng DAO, vì vậy tôi đã đi qua một số mẫu mã tương tự. Đừng nhớ tại sao, nhưng tôi quyết định không đi với cách tiếp cận như vậy (tôi nghĩ nó không hoạt động tốt trong mọi trường hợp, có thể phân cấp lớp là bắt buộc). Ví dụ của bạn không hoạt động :) +1 P.S. Một số hướng dẫn mở rộng mà tôi đã tìm thấy: http://www.artima.com/weblogs/viewpost.jsp?thread=208860 –

+0

Tôi đã tìm thấy bài viết gốc mà tôi đã xóa bài viết này (ví dụ ở trên được trích xuất từ ​​một trong những công việc của chúng tôi- dự án): http://tutorials.jenkov.com/java-reflection/generics.html#fieldtypes Bài viết nói rằng điều này chỉ hoạt động với các trường công cộng, nhưng điều đó không đúng, bạn có thể truy cập các trường được bảo vệ và riêng tư thông qua sự phản chiếu (chỉ sử dụng getDeclaredField thay vì getField) – esaj

+1

Điều này không trả lời câu hỏi. Điều này nhận được loại được sử dụng để khai báo một trường. Điều này có liên quan như thế nào? – newacct

39

Tôi thích giải pháp từ

http://www.nautsch.net/2008/10/28/class-von-type-parameter-java-generics/

public class Dada<T> { 

    private Class<T> typeOfT; 

    @SuppressWarnings("unchecked") 
    public Dada() { 
     this.typeOfT = (Class<T>) 
       ((ParameterizedType)getClass() 
       .getGenericSuperclass()) 
       .getActualTypeArguments()[0]; 
    } 
... 
+0

Giải pháp này hoạt động tốt cho tôi. Lợi thế là không cần phải vượt qua các thông số bổ sung như các giải pháp khác được đề cập. Bất kỳ vấn đề khi sử dụng này? –

+0

nó vẫn hoạt động tốt – wutzebaer

+11

Điều này sẽ chỉ hoạt động nếu lớp thời gian chạy là một lớp con trực tiếp của siêu lớp chung. –