iteye_17871
2012-09-22 11:12
浏览 412
已采纳

Java 反射:怎么取出类的泛型类型

[code="java"]
public class BaseHello {
private Class entityClass;

 public BaseHello(){
     //entityClass怎么赋值?(怎么能知道entityClass就是代表Personal这个类?)
 }

}
[/code]
[code="java"]
public static void main(String[] args) {
BaseHello pdao = new BaseHello();
System.out.println(pdao);
}
[/code]
如注释的问题:在BaseHello的构造方法中,怎么给entityClass赋值?

  • 写回答
  • 关注问题
  • 收藏
  • 邀请回答

7条回答 默认 最新

  • jinnianshilongnian 2012-09-22 11:19
    已采纳

    ParameterizedType parameterizedType = (ParameterizedType)this.getClass().getGenericSuperclass();

    entityClass= (Class)(parameterizedType.getActualTypeArguments()[0]);

    已采纳该答案
    打赏 评论
  • iteye_5246 2012-09-22 11:25

    [code="java"] Field[] fs = clazz.getDeclaredFields(); // 得到所有的fields

    for(Field f : fs)
    {
    Class fieldClazz = f.getType(); // 得到field的class及类型全路径

    if(fieldClazz.isPrimitive())  continue;  //【1】 //判断是否为基本类型
    
    if(fieldClazz.getName().startsWith("java.lang")) continue; //getName()返回field的类型全路径;
    
    if(fieldClazz.isAssignableFrom(List.class)) //【2】
    { 
             Type fc = f.getGenericType(); // 关键的地方,如果是List类型,得到其Generic的类型
    
             if(fc == null) continue;
    
             if(fc instanceof ParameterizedType) // 【3】如果是泛型参数的类型 
            { 
                   ParameterizedType pt = (ParameterizedType) fc;
    
                   Class genericClazz = (Class)pt.getActualTypeArguments()[0]; //【4】 得到泛型里的class类型对象。
    
                   m.put(f.getName(), genericClazz);
    
                   Map<String, Class> m1 = prepareMap(genericClazz);
    
                   m.putAll(m1); 
             } 
      } 
    

    }[/code]

    打赏 评论
  • zx527291227 2012-09-22 14:15

    [url]http://zx527291227.iteye.com/blog/1679332[/url]
    可以看下这个,这是rapid-framework通用框架,里面有讲Base,

    [code="java"]public class UserDao extends BaseHibernateDao{

    @Override  
    public Class getEntityClass() {  
        return User.class;  
    }
    

    }[/code]

    你看下这样获取是否是你要的

    打赏 评论
  • 「已注销」 2012-09-22 14:30

    不要再纠结这个问题了,这个没有解决方案,曾经和你一样的想法,记不清哪儿看的了,这个牵涉到泛型的擦除远离。

    大意是:
    1. 泛型编译时会推导擦除
    2. 只有在编译时保存了类型信息时才能获得,运行时的泛型信息因为类型擦除所以肯定获取不到泛型的具体信息

    详细测试见:
    [code="java"]
    public class TypesTest extends TestCase {
    Map a;
    Inner b;
    List[][]> c;
    List d;
    Set e;
    Outer.Inner f;

        private ParameterizedType mapStringInteger;
        private ParameterizedType innerFloatDouble;
        private ParameterizedType listSetStringArray;
        private ParameterizedType listString;
        private ParameterizedType setString;
        private ParameterizedType outerInner;
        private GenericArrayType setStringArray;
    
        @Override
        protected void setUp() throws Exception {
                super.setUp();
                mapStringInteger = (ParameterizedType) getClass().getDeclaredField("a")
                                .getGenericType();
                innerFloatDouble = (ParameterizedType) getClass().getDeclaredField("b")
                                .getGenericType();
                listSetStringArray = (ParameterizedType) getClass().getDeclaredField(
                                "c").getGenericType();
                listString = (ParameterizedType) getClass().getDeclaredField("d")
                                .getGenericType();
                setString = (ParameterizedType) getClass().getDeclaredField("e")
                                .getGenericType();
                outerInner = (ParameterizedType) getClass().getDeclaredField("f")
                                .getGenericType();
                setStringArray = (GenericArrayType) listSetStringArray
                                .getActualTypeArguments()[0];
    
                System.out.println(UtilJson.getObjectMapper()
                                .writerWithType(TypesTest.class).writeValueAsString(this));
                ;
        }
    
        class Inner<T1, T2> {
        }
    
        static class Outer<T> {
                class Inner {
                }
        }
    

    }
    [/code]

    打赏 评论
  • 「已注销」 2012-09-22 15:04

    因为类的成员变量在编译时会保留其类型信息的。
    如下E是泛型类型,Set e,在类型推导时会替换为Object的,所以你无法获取到类型信息,而e2,定义时就包含了类型信息,故可以获取到。
    [code="java"]
    public class TypesTest {
    Set e;
    Set e2;
    }
    [/code]

    完整测试代码如下
    [code="java"]
    import java.lang.reflect.GenericArrayType;
    import java.lang.reflect.ParameterizedType;
    import java.lang.reflect.Type;
    import java.util.List;
    import java.util.Map;
    import java.util.Set;

    import org.junit.Test;

    public class TypesTest {
    Map a;
    Inner b;
    List[][]> c;
    List d;
    Set e;
    Outer.Inner f;

    private ParameterizedType mapStringInteger;
    private ParameterizedType innerFloatDouble;
    private ParameterizedType listSetStringArray;
    private ParameterizedType listString;
    private ParameterizedType setString;
    private ParameterizedType outerInner;
    private GenericArrayType setStringArray;
    
    private String toString(ParameterizedType parameterizedType) {
        Type[] types = parameterizedType.getActualTypeArguments();
        String ret = "\n\t" + parameterizedType + "\n\t\t泛型个数:" + types.length + "==>";
        for (Type type : types) {
            ret += type + ", ";
        }
        return ret;
    }
    
    @Test
    public void main() throws Exception {
        mapStringInteger = (ParameterizedType) getClass().getDeclaredField("a").getGenericType();
        innerFloatDouble = (ParameterizedType) getClass().getDeclaredField("b").getGenericType();
        listSetStringArray = (ParameterizedType) getClass().getDeclaredField("c").getGenericType();
        listString = (ParameterizedType) getClass().getDeclaredField("d").getGenericType();
        setString = (ParameterizedType) getClass().getDeclaredField("e").getGenericType();
        outerInner = (ParameterizedType) getClass().getDeclaredField("f").getGenericType();
        setStringArray = (GenericArrayType) listSetStringArray.getActualTypeArguments()[0];
    
        System.out.println("a Map<String, Integer> 推导擦除后类型信息:" + toString(mapStringInteger));
        System.out.println();
        System.out.println("b Inner<Float, Double> 推导擦除后类型信息:" + toString(innerFloatDouble));
        System.out.println();
        System.out.println("c List<Set<String>[][]> 推导擦除后类型信息:" + toString(listSetStringArray));
        System.out.println();
        System.out.println("d List<String> 推导擦除后类型信息:" + toString(listString));
        System.out.println();
        System.out.println("e Set<String> 推导擦除后类型信息:" + toString(setString));
        System.out.println();
        System.out.println("f Outer<String>.Inner 推导擦除后类型信息:" + toString(outerInner));
        System.out.println();
        System.out.println("c List<Set<String>[][]> List第二层Set的泛型推导信息:" + setStringArray);
    }
    
    class Inner<T1, T2> {
    }
    
    static class Outer<T> {
        class Inner {
        }
    }
    

    }
    [/code]

    打赏 评论
  • wangsong76 2012-09-22 17:00

    你调用的无参的构造函数:
    BaseHello pdao = new BaseHello();

    相当于变成了这样:
    [code="java"]
    public class BaseHello {

    private Personal entityClass;

     public BaseHello(){   
         //entityClass怎么赋值?(怎么能知道entityClass就是代Personal这个类?) 
           你觉得这个地方你能怎么赋值?参数都不带!你想给entityClass赋值,就需要用带参数的构造函数。简单的事情不要整复杂了。
     }  
    
      public BaseHello(Class<T> arg){   
      这个地方你晓得怎么赋值了吧?
    

    }

    }

    [/code]

    打赏 评论
  • kyan54 2012-09-23 09:52

    [code="java"]

    import java.lang.reflect.ParameterizedType;
    import java.lang.reflect.Type;

    /**

    • 反射工具类
      */
      @SuppressWarnings("unchecked")
      public class ReflectUtils {

      /**

      • 获得超类的参数类型,取第一个参数类型
      • @param 类型参数
      • @param clazz 超类类型 */ @SuppressWarnings("rawtypes") public static Class getClassGenricType(final Class clazz) { return getClassGenricType(clazz, 0); }

      /**

      • 根据索引获得超类的参数类型
      • @param clazz 超类类型
      • @param index 索引 */ @SuppressWarnings("rawtypes") public static Class getClassGenricType(final Class clazz, final int index) { Type genType = clazz.getGenericSuperclass(); if (!(genType instanceof ParameterizedType)) { return Object.class; } Type[] params = ((ParameterizedType)genType).getActualTypeArguments(); if (index >= params.length || index < 0) { return Object.class; } if (!(params[index] instanceof Class)) { return Object.class; } return (Class) params[index]; } } [/code] [code="java"] public class PojoRawMapper implements RowMapper{ protected Class entityClass;

      public PojoRawMapper() {
      entityClass = ReflectUtils.getClassGenricType(getClass());
      }
      [/code]

    打赏 评论

相关推荐 更多相似问题