`
RyanPoy
  • 浏览: 51219 次
  • 性别: Icon_minigender_1
  • 来自: 长沙
社区版块
存档分类
最新评论

请教关于得到泛型的class

阅读更多
在发帖之前,一直在考虑。该不该发。查了查我的问题。也没有找到一个解决方案。所以,还是来发帖了。就发在新手帖吧。也许真的只是一个新手的问题。


先描述一下问题。有这个一个类:
public class Test<T>
{
}

要得到T的class。
如果看到这,请继续看下文,千万不要给出一句:
[color=red]
Class<T> entityClass = (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0]; 
[/color]
的答复。因为,我已经试过了。

一直没有仔细研究泛型这个东西。所以直接上网查了。
基本上找到这样一个方法:
Class<T> entityClass = (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0]; 


于是,依葫芦画瓢:
public class Test<T>
{
	Class<T> clazz;

	public Test()
	{
		clazz = (Class<T>) ((ParameterizedType) this.getClass().getGenericSuperclass()).getActualTypeArguments()[0];
	}
	
	public static void main(String[] args)
	{
		Test<Integer> t = new Test<Integer>();
	}
}


执行后抛出异常如下:
Exception in thread "main" java.lang.ClassCastException: java.lang.Class cannot be cast to java.lang.reflect.ParameterizedType
	at Test.<init>(Test.java:9)
	at Test.main(Test.java:14)


查找原因。发现,java中的泛型采用擦拭法。无法得到自己本身的泛型。而调用getGenericSuperclass()方法得到的是父类的泛型
所以,再次修改代码:
class Father<T>
{
	
}

public class Test<T> extends Father<T>
{
	Class<T> clazz;

	public Test()
	{
		clazz = (Class<T>) ((ParameterizedType) this.getClass().getGenericSuperclass()).getActualTypeArguments()[0];
		//((ParameterizedType) this.getClass().getGenericSuperclass()).getActualTypeArguments();
	}
	
	public static void main(String[] args)
	{
		Test<Integer> t = new Test<Integer>();
	}
}


运行后出现如下异常:
Exception in thread "main" java.lang.ClassCastException: sun.reflect.generics.reflectiveObjects.TypeVariableImpl cannot be cast to java.lang.Class
	at Test.<init>(Test.java:14)
	at Test.main(Test.java:20)

这下郁闷了。按道理说,这个是没有问题的。
于是我再次修改代码。把15行的注释打开,把14行注释掉。于是,代码如下:
class Father<T>
{
	
}

public class Test<T> extends Father<T>
{
	Class<T> clazz;

	public Test()
	{
		//clazz = (Class<T>) ((ParameterizedType) this.getClass().getGenericSuperclass()).getActualTypeArguments()[0];
		((ParameterizedType) this.getClass().getGenericSuperclass()).getActualTypeArguments();
	}
	
	public static void main(String[] args)
	{
		Test<Integer> t = new Test<Integer>();
	}
}

这次,没有抱任何异常。那么也就是说:getActualTypeArguments()[0] 无法强制转化成为Class<T>类型。乖乖,我本来就要得到这个类型。现在就差一步之遥了。

请问,我该如何得到了?



分享到:
评论
9 楼 yaojianxiaoyu 2014-05-28  
看你貌似不知道怎么弄,



public class BaseDao<T>  implements IBaseDao<T> {

	/**
	 * 通过反射获得传入的类
	 * @return
	 */
	public Class<T> getEntityClass() {
		Type type = getClass().getGenericSuperclass();
		ParameterizedType pType = (ParameterizedType)type;
		Type[] params = pType.getActualTypeArguments();
		@SuppressWarnings("unchecked")
		Class<T> c = (Class<T>)params[0];
		return c;
	}
//在具体的dao中继承过去
public class UserDao extends BaseDao<User> {

	public static void main(String[] args) {
		UserDao u = new UserDao();
		@SuppressWarnings("unused")
		Class<User> user = u.getEntityClass();
		System.out.println( u.getEntityClass().getName());
//org.tony.model.User
/***
*这个方式主要是用来获得具体实体类的,方便做操作,不用每个方法都传入class 了。
**/
	}

8 楼 d_xxm 2013-01-18  
 
clazz = (Class<T>) ((ParameterizedType) this.getClass().getGenericSuperclass()).getActualTypeArguments()[0];


抛出异常是因为没有在子类指定泛型类型。。。

public class Test1<T> extends Father<Integer> {。。。} 
7 楼 jiajia11 2012-09-27  
其实第二种方法我觉得不是泛型的应用,你把<T>去掉也是可以传进去参数的。
在DAO的应用中为了抽象出共同代码是应该有父类的,子类对应不同的DAO实现类。
所以第一种实现方法是对的。(个人理解)
6 楼 sigon 2008-12-24  
也正在查这个问题,楼主这篇文章帮助很大,谢谢
5 楼 davidcen 2008-12-22  
public abstract class BaseDAOImpl<T> extends JpaDaoSupport implements
IBaseDao<T> {

protected String className = "";


@SuppressWarnings("unchecked")
protected BaseDAOImpl() {
TypeVariable[] typeVariables = getClass().getTypeParameters();
if (typeVariables != null && typeVariables.length > 0) {
className = typeVariables[0].getName();
}
}
...
}
4 楼 dajianshi 2008-09-26  
不是不行,只是有点Ugly
3 楼 RyanPoy 2008-07-18  
<p>总结。 <br/>对于解决方法1,要注意这样几点。 <br/>1). 只能取得父类的T.class,而且,要写一个子类,且子类在继承父类的时候,就要把类型给确定下来。即: </p>
<pre name='code' class='java'>public class Test extends Father&lt;Integer&gt;
{
}</pre>
<p>  <br/><br/>这样的话,其实Test在定义的时候就已经确定了类型了。 <br/><br/>2). 这种方式不灵活,非得一个父类,一个子类。那么如果有一个Dao</p>
<pre name='code' class='java'>public class Dao&lt;T&gt;
{
Class clazz;

public Dao()
{
clazz = (Class) ((ParameterizedType) this.getClass().getGenericSuperclass()).getActualTypeArguments()[0];
}
}</pre>
<p> <br/><br/>如果要针对具体类型的时候,那么就得一个子类</p>
<pre name='code' class='java'>public class UserDao extends Dao
{
}</pre>
<p> </p>
<p>同理,如果要操作多个对象,那么就有多个子类。这样,很冗余。 <br/><br/>对于解决方式2, <br/>1). 只需要一个类。而能解决所有的问题。</p>
<pre name='code' class='java'>public class Test &lt;T&gt;
{
} </pre>
<p> <br/><br/>2). 这个类需要一个带参数的构造。且这个参数就是泛型的class。也就是说,这个泛型的class是由外面传进去的。</p>
<pre name='code' class='java'>public class Test &lt;T&gt;
{
Class clazz;

public Test(Class clazz)
{
this.clazz = clazz;
}
}</pre>
<p> <br/><br/><br/>3). 这种方式没有冗余。同样,以一个Dao来举例。</p>
<pre name='code' class='java'>public class Dao&lt;T&gt;
{
Class clazz;

public Dao(Class clazz)
{
this.clazz = clazz;
}
}</pre>
<p> <br/>这样,如果有一个UserDao,我们只需要。</p>
<pre name='code' class='java'>Dao userDao = new Dao(User.class); </pre>
<p> <br/><br/>4). 这种方式对应于c++中的template更为接近。 </p>
<p>  </p>
<p> c++中:</p>
<pre name='code' class='cpp'>template &lt;class T&gt;
class Dao
{
public:
    Dao()    {}
    ~Dao()  {}
};

int main(int argc, char* argv[])
{
     Dao* dao = new Dao;
     delete dao;

     return 0;
} </pre>
<p> <br/>java中:</p>
<pre name='code' class='java'>public class Dao&lt;T&gt;
{
Class clazz;

public Dao(Class clazz)
{
this.clazz = clazz;
}

public static void main(String[] args)
{
Dao dao = new Dao(User.class);
}
}</pre>
<p> <br/><br/>两者唯一的区别在于。 <br/>1). c++代码中的构造方法可以不用参数,是一个默认构造就可以了。至于具体的是什么类型的参数。这个是在编译器编译成2进制文件时自动转化。 <br/><br/>2). java代码中的构造方法,需要传递一个Class,这个Class就是T的Class。表面上看,好像这样子不合理。但是实际上想想,也没有不合理的地方。因为</p>
<pre name='code' class='java'>Dao&lt;User&gt; dao = ...
</pre>
<p> </p>
<p>这个地方的时候,你就已经确定了是对User进行操作。那构造方法中传递一个User.Class,又有何不可呢? <br/><br/>综上,采用2种方式中的任意一种都可以。不过,我更加喜欢第2种。 <br/><br/><br/></p>
<p> </p>
2 楼 RyanPoy 2008-07-18  
解决方法2:

一个类就可以了。不过这个有点投机。
public class Test2<T>
{
	Class<T> clazz;

	@SuppressWarnings("unchecked")
	public Test2(Class<T> clazz)
	{
		this.clazz = clazz;
		System.out.println(clazz);
	}

	public static void main(String[] args)
	{
		Test2<Integer> t = new Test2<Integer>(Integer.class);
	}
}

1 楼 RyanPoy 2008-07-18  
自己找到了解决方法。有2种方式。
1:
先有一个父类
public class Father<T>
{
	Class<T> clazz;

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



然后有一个子类:
public class Test1 extends Father<Integer>
{
	public Test1()
	{
		System.out.println(clazz);
	}

	public static void main(String[] args)
	{
		Test1 t = new Test1();
	}
}

相关推荐

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

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

    关于java的泛型.doc

    关于Java的泛型,这是Java 5.0版本引入的一项重大特性,旨在提供类型安全的集合操作,并增强代码的重用性和灵活性。泛型允许程序员在设计类或接口时使用类型参数,使得类或接口可以处理任何数据类型,而不必为每种...

    C#泛型类、泛型方法、泛型接口、泛型委托的实例

    本文将深入探讨泛型类、泛型方法、泛型接口和泛型委托,并通过实例来阐述它们的应用。 首先,我们来看泛型类。泛型类是具有一个或多个类型参数的类。类型参数是在定义类时使用的占位符,实际的类型在创建类的实例时...

    关于java基础的泛型的练习

    Java泛型是Java SE 5.0引入的一个重要特性,它极大地增强了代码的类型安全...在进行"关于Java基础的泛型的练习"时,可以尝试编写不同的泛型类、泛型方法,体验泛型带来的便利,并理解其背后的类型系统和类型擦除机制。

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

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

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

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

    泛型dao 泛型dao 泛型dao

    如果你真能只用一个dao解决,那么祝贺你,你得到了一个虚拟数据层(高度抽象的数据接口)。这是一个比dao更高级的存在。 欢迎大家指正 -_- 虚心求教 代码层次: bean--&gt;dao--&gt;service--&gt;action 技术概述:1....

    java 一个关于泛型的简单例子

    public class MyFirstGeneric&lt;T&gt; { private T item; public MyFirstGeneric(T item) { this.item = item; } public T getItem() { return item; } public void setItem(T item) { this.item = item; } ...

    Java泛型和Class类用法示例

    Java泛型和Class类用法示例 Java泛型和Class类用法示例主要介绍了Java泛型和Class类用法,结合实例形式分析了java使用泛型限制class类避免强制类型转换相关操作技巧。本文将从以下几个方面详细讲解Java泛型和Class...

    关于java泛型的讲解

    【Java 泛型详解】 Java 泛型是自Java SE 1.5版本引入的一种强大的编程工具,它允许在类、接口和方法中使用类型参数,从而实现了参数化类型。泛型的主要目标是提高代码的安全性和可重用性,同时减少类型转换的繁琐...

    java泛型指南 经典

    #### 九、更多关于通配符 (*) ##### 9.1 通配符匹配 (wildcard capture) Java 编译器会在某些情况下自动推断出通配符的类型。这种自动推断称为通配符捕获 (wildcard capture)。 #### 十、泛型化老代码 将现有的...

    泛型实现小例

    在Java编程语言中,泛型是一种强大的特性,它允许我们在编写代码时指定类型参数,从而提高了代码的灵活性、安全性和可重用性。本篇我们将深入探讨“泛型实现小例”这一主题,通过实际的例子来理解泛型的使用。 首先...

    关于C#、java泛型的看法

    在编程世界中,C#和Java都是广泛应用的高级编程语言,它们都支持泛型这一强大的特性,以提高代码的类型安全性和重用性。本文将深入探讨C#和Java在泛型实现上的异同,帮助开发者更好地理解和利用这两种语言的泛型功能...

    泛型学习和泛型接口和泛型经典示例

    泛型学习和泛型接口和泛型经典示例

    泛型java的泛型知识,非常有用

    - 定义泛型类时,类型参数写在尖括号内,如 `class TestGen, V&gt;`。 - 实例化泛型对象时,需要指定类型参数的具体类型,如 `TestGen, String&gt; t = new TestGen, String&gt;()`。 - `extends` 关键字在泛型中的作用是...

    SSH泛型代码实例

    SSH泛型代码实例是关于Java编程中的一种常见技术——Spring、Struts和Hibernate(SSH)框架结合使用泛型的应用示例。泛型是Java SE 5.0引入的一个重要特性,它允许在编译时检查类型安全,并且所有的强制转换都是自动...

    java 继承泛型类示例

    了解这些概念后,我们可以看到`GenericClass.java`文件可能包含了关于如何创建和使用继承泛型类的实际代码示例。而`Java.jpg`可能是用于辅助解释的图像,比如类结构图或代码截图。在实际学习过程中,结合代码和图像...

    【Flutter】Dart 泛型 ( 泛型类 泛型方法 特定类型约束的泛型 ).zip

    【Flutter】Dart 泛型 ( 泛型类 | 泛型方法 | 特定类型约束的泛型 ) https://hanshuliang.blog.csdn.net/article/details/114059611 博客源码快照

Global site tag (gtag.js) - Google Analytics