【问题标题】:Java generics - get class? [duplicate]Java 泛型 - 获取类? [复制]
【发布时间】:2011-06-17 18:07:57
【问题描述】:

我有一个列表,编程如下:public class MyList<T>。有什么方法可以使用 T 变量来获取类的名称(这样我就可以从 MyList 中知道 T 是 String、Socket 等)吗?

编辑:没关系,找到答案here

【问题讨论】:

    标签: java generics


    【解决方案1】:

    简答:你不能。

    长答案

    由于泛型在 Java 中的实现方式,泛型类型 T 不会在运行时保留。不过,您可以使用私有数据成员:

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

    使用示例:

    Foo<Integer> test = new Foo<Integer>(Integer.class);
    

    【讨论】:

      【解决方案2】:

      我喜欢来自

      的解决方案

      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];
          }
      ...
      

      【讨论】:

      • 这个解决方案对我来说很好。优点是不需要像提到的其他解决方案那样传递额外的参数。使用时有什么问题吗?
      • 它仍然可以正常工作
      • 这只有在运行时类是通用超类的直接子类时才有效。
      • 这个适用于在现代框架中非常流行的动态代理。
      • 线程“主”java.lang.ClassCastException 中的异常:java.lang.Class 无法转换为 java.lang.reflect.ParameterizedType
      【解决方案3】:

      您正在看到Type Erasure 的结果。从那个页面...

      当一个泛型类型被实例化时, 编译器通过 一种称为类型擦除的技术—— 编译器删除所有的过程 类型参数相关信息 并在类中键入参数或 方法。类型擦除启用 Java 使用泛型的应用程序 保持二进制兼容性 Java 库和应用程序 是在泛型之前创建的。

      例如,Box 是 翻译成 Box 类型,即 称为原始类型——原始类型是 泛型类或接口名称 没有任何类型参数。 这意味着 你不知道是什么类型的 泛型类正在使用的对象 运行时。

      这也看起来像这样的question,其中有一个pretty good answer as well

      【讨论】:

        【解决方案4】:

        我不能 100% 确定这是否适用于所有情况(至少需要 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();
                }
            }    
        }
        

        这将输出:

        字段映射的类型为 Map
        字段映射的参数化类型为 A
        字段映射的参数化类型为 B

        【讨论】:

        • 有一次我在重构General DAO的过程中尝试做类似的事情,所以我浏览了一些类似的代码示例。不记得为什么,但我决定不采用这种方法(我认为它在所有情况下都不能很好地工作,也许类层次结构是强制性的)。您的示例确实有效:) +1 P.S.我发现了一些扩展教程:artima.com/weblogs/viewpost.jsp?thread=208860
        • 我找到了我从中提取的原始文章(上面的示例摘自我们的一个工作项目):tutorials.jenkov.com/java-reflection/generics.html#fieldtypes 文章说这仅适用于公共字段,但事实并非如此是的,您也可以通过反射访问受保护和私有字段(只需使用 getDeclaredField 而不是 getField)
        • 这没有回答问题。这将获取用于声明字段的类型。这有什么关系?
        【解决方案5】:

        我可以通过这种方式获得泛型类型的 Class:

        class MyList<T> {
          Class<T> clazz = (Class<T>) DAOUtil.getTypeArguments(MyList.class, this.getClass()).get(0);
        }
        

        您需要此文件中的两个函数:http://code.google.com/p/hibernate-generic-dao/source/browse/trunk/dao/src/main/java/com/googlecode/genericdao/dao/DAOUtil.java

        更多解释:http://www.artima.com/weblogs/viewpost.jsp?thread=208860

        【讨论】:

        • 这里,MyList.class 和 this.getClass() 都是同一个值!!
        猜你喜欢
        • 2011-09-13
        • 1970-01-01
        • 1970-01-01
        • 2015-11-20
        • 2011-05-11
        • 2021-02-02
        • 1970-01-01
        • 2016-04-19
        • 2022-01-18
        相关资源
        最近更新 更多