`
langgufu
  • 浏览: 2311993 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

在泛型中得到T.class

 
阅读更多

在使用Spring的JdbcTemplate实现DAO的时候,经常会用到一个类ParameterizedBeanPropertyRowMapper。它的静态方法newInstance()接受一个Class类型的参数,用于将ResultSet中的属性映射到传入的这个Class类型的Bean对象中,再组成列表返回。

如果要想把这个DAO做成泛型的,就必须要知道Class的类型。但是直接写成T.class显然是不行的。从网上查了不少资料,结果只有一个,由于Java的泛型实现使用了“擦拭法”(具体细节没深究,呵呵),导致Java的泛型不能直接获取到自身的声明的泛型类型。

不过从江南白衣的blog文章里搜到了有用的东西:使用反射来获得“T.class”。

原文地址:http://www.blogjava.net/calvin/archive/2009/12/10/43830.html

主要用到的是这么一句:

view plaincopy to clipboardprint?
Class <T> entityClass = (Class <T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
Class <T> entityClass = (Class <T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];


我查询了Java API,在Class类中有这么两个方法: getGenericInterfaces()和getGenericSuperclass()

先来看看这两个方法都是干什么用的:

1. public Type getGenericSuperclass()

用来返回表示当前Class 所表示的实体(类、接口、基本类型或 void)的直接超类的Type。如果这个直接超类是参数化类型的,则返回的Type对象必须明确反映在源代码中声明时使用的类型。比如:

view plaincopy to clipboardprint?
package com.mot.hyena.test;
import java.lang.reflect.ParameterizedType;
public class GT1 extends GT2<Integer>{
public static void main(String[] args) {
System.out.println(((ParameterizedType)new GT1().getClass().getGenericSuperclass()));
}
}
package com.mot.hyena.test;
import java.lang.reflect.ParameterizedType;
public class GT1 extends GT2<Integer>{
public static void main(String[] args) {
System.out.println(((ParameterizedType)new GT1().getClass().getGenericSuperclass()));
}
}

则输出结果即为:com.mot.hyena.test.GT2<java.lang.Integer>

 

如果此Class代表的是Object 类、接口、基本类型或 void,则返回 null。。如果此对象表示一个数组类,则返回表示 Object 类的 Class 对象。

 

2. public Type[] getGenericInterfaces()

与上面那个方法类似,只不过Java的类可以实现多个接口,所以返回的Type必须用数组来存储。

 

 

以上两个方法返回的都是Type对象或数组,在我们的这个话题中,Class都是代表的参数化类型,因此可以将Type对象Cast成ParameterizedType对象。而 ParameterizedType对象有一个方法, getActualTypeArguments()。

public Type[] getActualTypeArguments()

用来返回一个Type对象数组,这个数组代表着这个Type声明中实际使用的类型。接着使用上面的例子:

view plaincopy to clipboardprint?
package com.mot.hyena.test;
import java.lang.reflect.ParameterizedType;
public class GT1 extends GT2<Integer>{
public static void main(String[] args) {
System.out.println(((ParameterizedType)new GT1().getClass().getGenericSuperclass()).getActualTypeArguments()[0]);
}
}
package com.mot.hyena.test;
import java.lang.reflect.ParameterizedType;
public class GT1 extends GT2<Integer>{
public static void main(String[] args) {
System.out.println(((ParameterizedType)new GT1().getClass().getGenericSuperclass()).getActualTypeArguments()[0]);
}
}

这次的显示结果将是:class java.lang.Integer

因此,我们可以通过继承+反射的方法,来的到T.class。

需要说明的是,江南白衣使用的方法是将关键语句

Class < T > entityClass = (Class < T > ) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[ 0 ];

放在了超类,也就是声明泛型的那个类的构造方法中。这样一来,子类在继承具有泛型的超类时,会自动调用超类的构造方法。在此超类的构造方法中,调用的getClass返回的是子类的Class类型(与通常的重写机制有悖,呵呵,有待深究,但测试结果确是如此),则在子类中就无需再显式地使用 getGenericInterfaces()和getGenericSuperclass()等方法了。

接着,再使用(Class<T>)对 getActualTypeArguments()返回的元素做casting,即可得到所谓的T.class。

分享到:
评论

相关推荐

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

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

    654.652.JAVA基础教程_反射-获取运行时类的父类及父类的泛型(654).rar

    在Java中,泛型是一种在编译时类型安全的机制,用于处理多种数据类型。然而,由于类型擦除,运行时无法直接获取泛型类型参数。但是,我们可以通过检查方法或字段的签名来间接获取这些信息。 例如,假设我们有一个...

    虚拟数据层 Struts2、Hibernate、Spring整合的泛型DAO Version 2010.9.27

    泛型daoimpl :GenericDaoImpl&lt;T, ID extends Serializable&gt; implements GenericDao&lt;T, ID&gt; 必须提供的构造方法,以便创建实例的时候就知道具体实体的类型。 daoimpl :PersonDAOImpl extends GenericDaoImpl, ...

    Java Web程序运用中泛型DAO的作用.zip

    在泛型DAO中,我们可以使用泛型来定义一个通用的DAO接口或类,这个接口或类可以操作任何类型的实体对象,而不是特定的某一种类型。这样做有以下几个显著的优点: 1. **类型安全**:泛型可以确保在编译阶段就检测到...

    泛型JAVA指南.pdf

    例如,类型擦除(Erasure)是Java泛型的一个重要概念,意味着泛型信息在编译后将被擦除,使得在运行时无法获得泛型类型的详细信息。因此,不能使用instanceof检查泛型类型的参数化形式,只能检查其擦除形式,例如...

    泛型dao 泛型dao 泛型dao

    泛型daoimpl :GenericDaoImpl&lt;T, ID extends Serializable&gt; implements GenericDao&lt;T, ID&gt; 必须提供的构造方法,以便创建实例的时候就知道具体实体的类型。 daoimpl :PersonDAOImpl extends GenericDaoImpl, ...

    java 泛型类的类型识别示例

    4. **利用`Class&lt;T&gt;`作为泛型约束**:有时候,我们可以在泛型类中使用`Class&lt;T&gt;`作为参数或字段,这样可以在运行时获取类型信息。例如: ```java public class MyClass&lt;T&gt; { private final Class&lt;T&gt; clazz; ...

    高级无敌,c#泛型例子

    3. **泛型方法**:在类或接口中定义的方法也可以是泛型的,如`void Swap&lt;T&gt;(ref T a, ref T b)`,它接受两个相同类型的引用参数并交换其值。 4. **约束**:可以对泛型类型参数添加约束,限制它可以是什么类型。比如...

    TypeScript泛型类 - 把类作为参数类型的泛型类.zip

    在TypeScript中,我们可以在类声明中使用尖括号 `&lt;T&gt;` 来定义一个泛型类。`T` 是一个占位符,代表一个未知的类型。当实例化类时,我们可以传入具体的类型参数来替换 `T`,从而得到具有特定类型特性的实例。 2. 类...

    Java重要的泛型使用方法.docx

    在这个版本中,我们定义了一个类型参数`T`,表示“类型”。在实例化`MyArrayList`类时,我们可以指定具体的类型,例如`MyArrayList&lt;Integer&gt;`或`MyArrayList&lt;String&gt;`。这种设计方式确保了类型安全性和代码的复用性...

    C#泛型学习和理解代码示例

    C#泛型是.NET框架中的一个强大特性,它允许我们创建可重用的类型,这些类型可以在多种数据类型上工作,而无需重复编写相同代码。泛型的主要目标是提高代码的类型安全性和性能,同时减少类型转换的需要。在本文中,...

    反射与泛型

    假设我们已经得到了T的实际类型,我们可以使用`Class.newInstance()`方法或`Constructor.newInstance()`来创建对象。但要注意,`Class.newInstance()`方法要求类必须有无参构造器,而`Constructor.newInstance()`则...

    Java编程语言中的泛型

    无论您是否熟悉其他编程语言中的类似结构,如C++的模板,都将通过本文获得对Java泛型深入的理解。 #### 二、泛型的基本概念 **1. 泛型的目的** 泛型的主要目的是为了提高代码的复用性和安全性。在Java中,泛型...

    C#基础之泛型

    在C#编程语言中,泛型是一种强大的特性,它首次出现在C# 2.0版本,并且得到了公共语言运行库(CLR)的支持。泛型的主要目标是提供类型安全、高效的数据容器,避免了不必要的装箱拆箱操作,从而提升了性能。本文将深入...

    java泛型类和函数

    这种机制在Java 5中被引入,并在集合框架(如`List`、`Set`和`Map`等)中得到了广泛应用。 #### 泛型的优点 - **类型安全**:使用泛型可以避免运行时的`ClassCastException`异常。 - **代码重用**:通过使用泛型,...

    泛型和泛型集合类用法

    在.NET Framework 2.0及以后版本中,泛型得到了广泛的应用和支持。通过使用泛型,可以显著提高代码的灵活性和可维护性,同时减少类型转换带来的开销。 #### 二、泛型集合类简介 .NET Framework 2.0引入了一系列...

    泛型实际应用(简介)

    在计算机科学领域,尤其是面向对象编程中,泛型是一种重要的编程技术,它允许程序员编写类型安全且灵活的代码,这种代码能够处理多种数据类型,同时保持类型检查的安全性。通过使用泛型,可以在不牺牲类型安全性、...

    泛型实现小例

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

    JAVAfanxing.rar_泛型

    泛型在Java集合框架中得到了广泛的应用,例如`ArrayList&lt;E&gt;`、`HashMap, V&gt;`等。此外,它也用于接口(如`Comparable&lt;T&gt;`)、枚举(`EnumSet&lt;E&gt;`)、方法返回类型以及匿名类等场景。 总的来说,Java泛型提供了一种...

    java 泛型接口示例

    在这个例子中,`GenericInterface`是一个泛型接口,`T`是它的类型参数,`operate()`方法接受一个类型为`T`的参数。 2. **类型参数的约束** 我们还可以对类型参数进行约束,限制它可以是哪些类型的子类。例如,...

Global site tag (gtag.js) - Google Analytics