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

相关推荐

    Java-Java反射与泛型教程

    2. **类型擦除**: 泛型在编译后会进行类型擦除,因此在运行时无法直接获取泛型类型信息。但泛型可以提供编译时的类型检查。 3. **通配符**: 通配符用于表示对类型的一般限制,如`?`表示任何类型,`? extends Number...

    利用java反射、注解及泛型模拟ORM实现

    1. 反射(Reflection):Java反射机制允许程序在运行时动态地获取类的信息(如类名、方法名、参数类型等)并调用其方法。通过`Class`类,我们可以实例化未知类型的对象,调用私有方法,访问私有字段,以及检查类的...

    java * 反射工具类. 提供调用getter/setter方法, 访问私有变量, 调用私有方法, 获取泛型类型Class

    提供调用getter/setter方法, 访问私有变量, 调用私有方法, 获取泛型类型Class,java * 反射工具类. 提供调用getter/setter方法, 访问私有变量, 调用私有方法, 获取泛型类型Class,java * 反射工具类. 提供调用getter/...

    Java泛型类型擦除后的补偿

    - 反射API在泛型类型擦除后仍然能获取到泛型信息,这主要通过泛型类的类型参数的实际类型参数化实例(TypeToken)来实现。 - 这使得在运行时可以进行一些泛型相关的操作,如创建参数化的类实例。 总结来说,Java...

    Java 理论和实践 了解泛型

    10. 泛型的局限性:由于类型擦除,泛型不能用于基本类型,所以Java提供了如`ArrayList&lt;Integer&gt;`这样的容器,实际上内部是通过包装类`Integer`实现的。另外,泛型也不能用于静态方法和变量,因为它们不属于任何特定...

    Java泛型_Java中的泛型结构_

    Java泛型是Java编程语言中一个强大的特性,它允许在定义类、接口和方法时使用类型参数,从而实现参数化类型。泛型的主要目标是提高代码的类型安全性和重用性,减少类型转换的麻烦,并在编译时捕获可能的类型错误。...

    java反射与泛型综合例子

    总结来说,Java反射提供了在运行时探索和操作类的能力,而泛型则增强了类型安全和代码复用。在`Testrefl.java`的例子中,这两者结合在一起,实现了动态创建和操作对象的能力,显示了Java编程的强大灵活性。理解并...

    java 反射工具类. 提供调用getter/setter方法, 访问私有变量, 调用私有方法, 获取泛型类型Class

    提供调用getter/setter方法, 访问私有变量, 调用私有方法, 获取泛型类型Class, 被AOP过的真实类等工具函数.反射工具类. 提供调用getter/setter方法, 访问私有变量, 调用私有方法, 获取泛型类型Class, 被AOP过的真实...

    JAVA5泛型和反射

    泛型类型: 在 Java 5 之前,像 `Hashtable` 这样的集合类只能存储 `Object` 类型的数据,这意味着在使用集合时,程序员必须进行强制类型转换。这种转换可能导致 `ClassCastException`,增加了代码的脆弱性。泛型的...

    java反射,获取所有属性、方法以及List集合类

    尽管Java反射不直接支持泛型信息,但可以通过方法签名或字段类型来间接获取。例如,`List&lt;?&gt;`的`Class`类型是`java.util.List`,这意味着你不能直接获取泛型的实际类型参数。然而,你可以通过类型检查和转换来操作...

    Java反射泛型,实现数据库的动态增删改查等功能

    Java反射和泛型是两种强大的编程特性,它们在开发中有着广泛的应用,特别是在数据库操作的动态化场景下。本文将详细介绍如何结合这两种技术实现在Java中对MySQL、SQL Server或Oracle数据库进行动态的增删改查操作。 ...

    java 基于泛型与反射的通用 DAO

    这里的`&lt;T&gt;`就是泛型类型,`T`代表任何对象类型。通过这种方式,我们可以创建一个通用的DAO类,不指定具体的实体类,但在子类中指定时,编译器会进行类型检查,避免了类型转换的麻烦。 接着,我们讨论“反射”。...

    java泛型的内部原理及更深应用

    通过反射获取的类信息中,泛型类型将表现为原始类型,但在编译时,泛型信息可用于类型检查。 9. **集合框架中的泛型**:Java集合框架广泛使用了泛型,如ArrayList、LinkedList、HashMap等。使用泛型,可以确保集合...

    Java泛型的用法及T.class的获取过程解析

    Java泛型是Java编程语言中的一种重要特性,它允许开发者在编写代码时指定类型参数,从而提高代码的灵活性和可读性。本文将详细介绍Java泛型的用法 及T.class的获取过程解析。 一、泛型的基本概念 泛型是Java 5中...

    java泛型学习全面页面下载资料

    7. **泛型与反射**:讨论泛型如何与Java反射API交互,以及如何在反射中处理泛型类型。 8. **泛型与多态**:解释泛型如何影响类的继承和多态性,以及如何在泛型类的实例间进行方法重写。 9. **集合框架中的泛型**:...

    Java基础入门四泛型反射注解.pdf

    泛型是Java SE 5版本引入的一个新特性,它的主要目的是允许在使用类、接口和方法时能够引用到任何类型的对象,同时在编译期间就能进行类型检查,提供更安全的代码。泛型类和泛型方法可以提高代码的复用性,并减少...

    java,反射+注释+泛型+jdbc mysql练习项目代码

    1. **Java反射**:反射API允许我们在运行时动态地获取类的信息(如类名、方法名、参数类型等)并调用这些方法。在处理数据库操作时,反射常用于动态地创建数据库连接、执行SQL语句,甚至根据数据库表结构自动生成...

    Java1_5泛型.zip

    Java 1.5 泛型是Java编程语言中的一项重要特性,它于2004年发布,极大地提升了代码的类型安全性和可读性。泛型允许开发者在类、接口和方法中使用类型参数,从而在编译时就能检查类型错误,避免了运行时的类型转换...

    Java反射、泛型和注解实战之Spring核心注入IOC的实现

    通过这个实战项目,你可以深入理解Java反射、泛型和注解的用法,并且了解到如何利用它们构建一个基本的依赖注入系统,这将有助于你更好地理解和使用Spring框架。同时,这样的实践也有助于提升你的编程技能,使你能够...

    java5泛型新特性 pdf

    11. **泛型与反射**:在使用反射操作泛型类型时,需要注意类型信息在运行时是不可见的,需要通过其他方式(如注解或硬编码)来获取。 以上就是Java 5泛型新特性的一些关键点。通过这些特性,我们可以编写更安全、更...

Global site tag (gtag.js) - Google Analytics