0 0

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

public class BaseHello<T> {
	 private Class<T> entityClass;
	 
	 public BaseHello(){
		 //entityClass怎么赋值?(怎么能知道entityClass就是代表Personal这个类?)
	 }
}

	public static void main(String[] args) {
		BaseHello<Personal> pdao = new BaseHello<Personal>();
		System.out.println(pdao);
	}

如注释的问题:在BaseHello的构造方法中,怎么给entityClass赋值?

问题补充:请注意这句  BaseHello<Personal> pdao = new BaseHello<Personal>(); 我是调用 BaseHello 这个类本身的构造方法,而不是一个他的子类的构造方法。

问题补充:其实我是想实现这样的:
public class BaseHello<T>{
public Class<T> entityClass;
public BaseHello(Class a) {
this.entityClass = a;
}
}
public static void main(String[] args) throws Exception{
BaseHello pdao = new BaseHello(Personal.class);
System.out.println(pdao);
}
这样功能倒是能实现,但是 这句这么写真的感觉好别扭
BaseHello pdao = new BaseHello(Personal.class);
我是想有反射应该不用这么写吧?

问题补充:结帖:问题出在
public class BaseHello<T> {
private Class<T> entityClass;
public BaseHello(){
}
}
这个类在运行期会出现泛型擦除的情况。
所以只能如 jinnianshilongnian 朋友所提的两种方法了。
感谢大家的热心帮助,结贴!
2012年9月22日 11:12

7个答案 按时间排序 按投票排序

0 0

采纳的答案

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

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

2012年9月22日 11:19
0 0


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

/**
 * 反射工具类
 */
@SuppressWarnings("unchecked")
public class ReflectUtils {
	
	/**
	 * 获得超类的参数类型,取第一个参数类型
	 * @param <T> 类型参数
	 * @param clazz 超类类型
	 */
	@SuppressWarnings("rawtypes")
	public static <T> Class<T> 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];
	}
}

public class PojoRawMapper<T> implements RowMapper<Object>{
	protected Class<T> entityClass;
	
	public PojoRawMapper() {
		entityClass = ReflectUtils.getClassGenricType(getClass());
	}

2012年9月23日 09:52
0 0

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

相当于变成了这样:

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

      public BaseHello(Class<T> arg){   
      这个地方你晓得怎么赋值了吧?
}

}  

2012年9月22日 17:00
0 0

因为类的成员变量在编译时会保留其类型信息的。
如下E是泛型类型,Set<E> e,在类型推导时会替换为Object的,所以你无法获取到类型信息,而e2,定义时就包含了类型信息,故可以获取到。

public class TypesTest<E> {
	Set<E> e;
	Set<Integer> e2;
}


完整测试代码如下
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<String, Integer> a;
	Inner<Float, Double> b;
	List<Set<String>[][]> c;
	List<String> d;
	Set<String> e;
	Outer<String>.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 {
		}
	}
}

2012年9月22日 15:04
0 0

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

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

详细测试见:

public class TypesTest extends TestCase {
        Map<String, Integer> a;
        Inner<Float, Double> b;
        List<Set<String>[][]> c;
        List<String> d;
        Set<String> e;
        Outer<String>.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 {
                }
        }
}

2012年9月22日 14:30
0 0

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

public class UserDao extends BaseHibernateDao<User, Long>{  
  
    @Override  
    public Class getEntityClass() {  
        return User.class;  
    }
}


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

2012年9月22日 14:15
0 0

 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); 
             } 
      } 
}

2012年9月22日 11:25

相关推荐

    fantj2016#java-reader#10. Java反射---泛型1

    而不是创建一个Object列表,你可以参数化java.util.List来创建一个String String列表,如下所示:当通过反射在运行时检查可参数化类型本

    反射处理java泛型

    当我们声明了一个泛型的接口或类,或需要一个子类继承至这个泛型类,而我们又希望利用反射获取这些泛型参数信息。这是本文将要介绍的ReflectionUtil是为了解决这类问题的辅助工具类,为java.lang.reflect标准库的...

    java深度历险

    JAVA反射与动态代理 40 基本用法 40 处理泛型 42 动态代理 42 使用案例 43 参考资料 44 JAVA I/O 45 流 45 缓冲区 47 字符与编码 48 通道 49 参考资料 52 JAVA安全 53 认证 53 权限控制 55 加密、解密与签名 57 安全...

    Java高手真经 编程基础卷.part1.rar

    Java高级特性:反射、泛型、注释符、自动装箱和拆箱、枚举类、可变参数、可变返回类型、增强循环、静态导入。随书附赠光盘内容为《Java高手真经(编程基础卷):Java核心编程技术》各种原型包、系统源程序。

    Java高手真经 编程基础卷.part3.rar

    Java高级特性:反射、泛型、注释符、自动装箱和拆箱、枚举类、可变参数、可变返回类型、增强循环、静态导入。随书附赠光盘内容为《Java高手真经(编程基础卷):Java核心编程技术》各种原型包、系统源程序。

    Java高手真经 编程基础卷.part4.rar

    Java高级特性:反射、泛型、注释符、自动装箱和拆箱、枚举类、可变参数、可变返回类型、增强循环、静态导入。随书附赠光盘内容为《Java高手真经(编程基础卷):Java核心编程技术》各种原型包、系统源程序。

    Java高手真经 编程基础卷.part2.rar

    Java高级特性:反射、泛型、注释符、自动装箱和拆箱、枚举类、可变参数、可变返回类型、增强循环、静态导入。随书附赠光盘内容为《Java高手真经(编程基础卷):Java核心编程技术》各种原型包、系统源程序。

    java进阶技术:泛型、反射、注解

    泛型是Java SE 1.5的新特性,好处是在编译时检查类型安全,并且所有的强制转换都是自动和隐式的,以提高代码的重用率。JAVA反射机制是构建框架技术的基础所在。灵活掌握Java反射机制,对以后学习框架有很大的帮助。...

    Java核心编程技术源码

    Java高级特性:反射、泛型、注释符、自动装箱和拆箱、枚举类、可变参数、可变返回类型、增强循环、静态导入。随书附赠光盘内容为《Java高手真经(编程基础卷):Java核心编程技术》各种原型包、系统源程序。《Java高手...

    Java泛型和反射.ppt

    泛型,即“参数化类型”。一提到参数,最熟悉的就是定义方法时有形参,然后调用此方法时传递实参。那么参数化类型怎么理解呢?...在java中,只要给定类的名字,那么就可以通过反射机制来获得类的所有信息。

    java中获取泛型类的子类

    通过反射获得指定类的父类的泛型参数的实际类型

    基于java8新特性+反射机制实现list不同实体类互转.zip

    实现list不同泛型之间实体的互转,基于java8新特性+反射机制实现list不同实体类互转,将jdk8的流处理集合互转抽出来成一个工具类,实现lsit

    【Java面试+Java学习指南】 一份涵盖大部分Java程序员所需要掌握的核心知识

    Java基本数据类型 string和包装类 final关键字特性 Java类和包 抽象类和接口 代码块和代码执行顺序 Java自动拆箱装箱里隐藏的秘密 Java中的Class类和Object类 Java异常 解读Java中的回调 反射 泛型 枚举类 Java注解...

    Java 泛型(Generics)使用说明

    环境:Windows XP Professional、JDK 1.6、Ant 1.7 说明:Java泛型的动机是为解决类型转换在编译时不报错的问题。另外由于“范型编程”(Generic Programming)的推广,于是2004年JDK 5.0引用范型标准。本例子说明...

    泛型dao 泛型dao 泛型dao

    泛型 泛型类型的限定 3.反射 代码概述: bean :Person.java 这个人员类我就不说了 泛型dao接口 :GenericDao, ID extends Serializable&gt; 泛型作为DAO的通用接口 CRUD方法 dao接口 : PersonDAO extends ...

    java面试常用知识点.docx

    面向对象:类、继承、多态、包、接口、抽象类、泛型等 异常处理:try-catch-finally、异常分类及处理、自定义异常等 线程:线程创建、线程同步、线程池等 反射机制:Class、Field、Method、Constructor等 注解:...

    Java工程师面试复习指南

    Java基本数据类型 字符串和包装类 关键字最终特性 Java类和包 抽象类和接口 代码块和代码执行顺序 Java自动拆箱装箱里隐藏的秘密 Java中的Class类和Object类 Java异常 解读Java中的回调 反射 泛型 枚举类 Java注解和...

Global site tag (gtag.js) - Google Analytics