首先我们要知道java里定义了哪些类型。java的类型都实现了java.lang.reflect.Type的接口, 主要有五类:raw types, parameterized types, array types, type variables and primitive types。
raw types: 就是一般类型,如String, Number,等 parameterized types: 含泛型定义的类,如:List, Map, etc.. array types: 含泛型定义的数组,数组内可以是parameterized types或type variables,如<K> K[] type variables: 类型变量,不确定其类型。如:V, <V extends Number> primitive types: int, float, double, etc.. 在java内部有四个接口继承自Type,分别是GenericArrayType, ParameterizedType, TypeVariable<D>, WildcardType 。其中,array types实现自GenericArrayType;parameterized types实现自ParameterizedType;type variables实现自TypeVariable<D>;WildcardType是形如 ?, ? extends Number一类的type. 需要注意的是, Class也是Type的一种实现。
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;
/**
* 泛型工具类
*/
public class GenericsUtils {
/**
* 通过反射,获得指定类的父类的泛型参数的实际类型. 如BuyerServiceBean extends DaoSupport<Buyer>
*
* @param clazz
* clazz 需要反射的类,该类必须继承范型父类
* @param index
* 泛型参数所在索引,从0开始.
* @return 范型参数的实际类型, 如果没有实现ParameterizedType接口,即不支持泛型,所以直接返回
* <code>Object.class</code>
*/
@SuppressWarnings("unchecked")
public static Class getSuperClassGenricType(Class clazz, int index) {
Type genType = clazz.getGenericSuperclass();// 得到泛型父类
// 如果没有实现ParameterizedType接口,即不支持泛型,直接返回Object.class
if (!(genType instanceof ParameterizedType)) {
return Object.class;
}
// 返回表示此类型实际类型参数的Type对象的数组,数组里放的都是对应类型的Class, 如BuyerServiceBean extends
// DaoSupport<Buyer,Contact>就返回Buyer和Contact类型
Type[] params = ((ParameterizedType) genType).getActualTypeArguments();
if (index >= params.length || index < 0) {
throw new RuntimeException("你输入的索引"
+ (index < 0 ? "不能小于0" : "超出了参数的总数"));
}
if (!(params[index] instanceof Class)) {
return Object.class;
}
return (Class) params[index];
}
/**
* 通过反射,获得指定类的父类的第一个泛型参数的实际类型. 如BuyerServiceBean extends DaoSupport<Buyer>
*
* @param clazz
* clazz 需要反射的类,该类必须继承泛型父类
* @return 泛型参数的实际类型, 如果没有实现ParameterizedType接口,即不支持泛型,所以直接返回
* <code>Object.class</code>
*/
@SuppressWarnings("unchecked")
public static Class getSuperClassGenricType(Class clazz) {
return getSuperClassGenricType(clazz, 0);
}
/**
* 通过反射,获得方法返回值泛型参数的实际类型. 如: public Map<String, Buyer> getNames(){}
*
* @param Method
* method 方法
* @param int index 泛型参数所在索引,从0开始.
* @return 泛型参数的实际类型, 如果没有实现ParameterizedType接口,即不支持泛型,所以直接返回
* <code>Object.class</code>
*/
@SuppressWarnings("unchecked")
public static Class getMethodGenericReturnType(Method method, int index) {
Type returnType = method.getGenericReturnType();
if (returnType instanceof ParameterizedType) {
ParameterizedType type = (ParameterizedType) returnType;
Type[] typeArguments = type.getActualTypeArguments();
if (index >= typeArguments.length || index < 0) {
throw new RuntimeException("你输入的索引"
+ (index < 0 ? "不能小于0" : "超出了参数的总数"));
}
return (Class) typeArguments[index];
}
return Object.class;
}
/**
* 通过反射,获得方法返回值第一个泛型参数的实际类型. 如: public Map<String, Buyer> getNames(){}
*
* @param Method
* method 方法
* @return 泛型参数的实际类型, 如果没有实现ParameterizedType接口,即不支持泛型,所以直接返回
* <code>Object.class</code>
*/
@SuppressWarnings("unchecked")
public static Class getMethodGenericReturnType(Method method) {
return getMethodGenericReturnType(method, 0);
}
/**
* 通过反射,获得方法输入参数第index个输入参数的所有泛型参数的实际类型. 如: public void add(Map<String,
* Buyer> maps, List<String> names){}
*
* @param Method
* method 方法
* @param int index 第几个输入参数
* @return 输入参数的泛型参数的实际类型集合, 如果没有实现ParameterizedType接口,即不支持泛型,所以直接返回空集合
*/
@SuppressWarnings("unchecked")
public static List<Class> getMethodGenericParameterTypes(Method method,
int index) {
List<Class> results = new ArrayList<Class>();
Type[] genericParameterTypes = method.getGenericParameterTypes();
if (index >= genericParameterTypes.length || index < 0) {
throw new RuntimeException("你输入的索引"
+ (index < 0 ? "不能小于0" : "超出了参数的总数"));
}
Type genericParameterType = genericParameterTypes[index];
if (genericParameterType instanceof ParameterizedType) {
ParameterizedType aType = (ParameterizedType) genericParameterType;
Type[] parameterArgTypes = aType.getActualTypeArguments();
for (Type parameterArgType : parameterArgTypes) {
Class parameterArgClass = (Class) parameterArgType;
results.add(parameterArgClass);
}
return results;
}
return results;
}
/**
* 通过反射,获得方法输入参数第一个输入参数的所有泛型参数的实际类型. 如: public void add(Map<String, Buyer>
* maps, List<String> names){}
*
* @param Method
* method 方法
* @return 输入参数的泛型参数的实际类型集合, 如果没有实现ParameterizedType接口,即不支持泛型,所以直接返回空集合
*/
@SuppressWarnings("unchecked")
public static List<Class> getMethodGenericParameterTypes(Method method) {
return getMethodGenericParameterTypes(method, 0);
}
/**
* 通过反射,获得Field泛型参数的实际类型. 如: public Map<String, Buyer> names;
*
* @param Field
* field 字段
* @param int index 泛型参数所在索引,从0开始.
* @return 泛型参数的实际类型, 如果没有实现ParameterizedType接口,即不支持泛型,所以直接返回
* <code>Object.class</code>
*/
@SuppressWarnings("unchecked")
public static Class getFieldGenericType(Field field, int index) {
Type genericFieldType = field.getGenericType();
if (genericFieldType instanceof ParameterizedType) {
ParameterizedType aType = (ParameterizedType) genericFieldType;
Type[] fieldArgTypes = aType.getActualTypeArguments();
if (index >= fieldArgTypes.length || index < 0) {
throw new RuntimeException("你输入的索引"
+ (index < 0 ? "不能小于0" : "超出了参数的总数"));
}
return (Class) fieldArgTypes[index];
}
return Object.class;
}
/**
* 通过反射,获得Field泛型参数的实际类型. 如: public Map<String, Buyer> names;
*
* @param Field
* field 字段
* @param int index 泛型参数所在索引,从0开始.
* @return 泛型参数的实际类型, 如果没有实现ParameterizedType接口,即不支持泛型,所以直接返回
* <code>Object.class</code>
*/
@SuppressWarnings("unchecked")
public static Class getFieldGenericType(Field field) {
return getFieldGenericType(field, 0);
}
}
分享到:
相关推荐
综上所述,虽然Java泛型在编译后会进行类型擦除,但通过上述技巧,我们仍然能够在运行时获得关于泛型类实例化类型的一些信息。在实际开发中,这些方法可以帮助我们编写更加灵活和安全的代码。在示例文件`GenericRTTI...
泛型 泛型类型的限定 3.反射 代码概述: bean :Person.java 这个人员类我就不说了 泛型dao接口 :GenericDao, ID extends Serializable> 泛型作为DAO的通用接口 CRUD方法 dao接口 : PersonDAO extends ...
我们还可以创建嵌套的泛型类型,例如`Dictionary, TValue>`,其中`TKey`和`TValue`都是泛型类型参数。 10. **泛型与接口、抽象类的结合**: 泛型类型可以实现接口或继承抽象类。例如,`GenericStack<T>`可以实现`...
构造泛型类型是指通过为泛型类型参数指定具体类型而得到的实际类型。例如,如果你有一个泛型类`List<T>`,当你实例化`List<int>`时,`int`就是构造类型,它替代了泛型类型参数`T`。 #### 泛型类型实际参数(类型...
在Java编程语言中,泛型是一种强大的特性,它允许我们在编写代码时指定类型参数,从而提高了代码的灵活性、安全性和可重用性。本篇我们将深入探讨“泛型实现小例”这一主题,通过实际的例子来理解泛型的使用。 首先...
上篇文章给大家介绍了浅析C# 中的类型系统(值类型和引用类型),接下来通过本文给大家介绍下c# 泛型类型, 说下C#中的泛型,熟练地使用泛型能提高代码的重用性,使用我们代码瞬间就高大上了,当然只有一点点,真的...
到了JDK1.4,通过JSR#14的支持,泛型技术以插件的形式得到了更广泛的采纳,尽管当时的Java标准库并未针对泛型进行全面的改写。直至JDK1.5,泛型技术终于被正式集成到Java的核心功能中,不仅编译器原生支持泛型,整个...
通过定义一个或多个类型参数(如`T`),泛型类型可以被实例化为具体的类型,例如`Stack<int>`或`Stack<string>`。在实例化时,`T`会被替换为实际的数据类型,如整型或字符串,这使得编译器能够进行类型检查,确保在...
因此,虽然在编译期间我们能获得类型检查的好处,但在运行时,泛型接口和类的行为与无参数类型版本基本相同。 5. **通配符** 在某些情况下,我们可能不关心类型参数的具体类型,而只关心它是某个类的子类或者实现...
在.NET Framework 2.0及以后版本中,泛型得到了广泛的应用和支持。通过使用泛型,可以显著提高代码的灵活性和可维护性,同时减少类型转换带来的开销。 #### 二、泛型集合类简介 .NET Framework 2.0引入了一系列...
这里的`<>`告诉编译器根据变量声明时的泛型类型来推断实例化的泛型类型。 然而,Java 7的类型推导并不是完全的,它仅在构造器的参数化类型在上下文中明显声明时有效。例如,以下代码在Java 7中是不合法的,因为...
TypeScript的类型系统通常可以自动推断泛型类型,但在某些复杂的情况下,可能需要显式指定类型参数,以确保代码的类型正确性。 总结: 在TypeScript中,泛型类提供了一种强大的方式来创建高度可复用且类型安全的...
这意味着在运行时,泛型类型信息会被抹去,所有泛型类型都会转换成其对应的原始类型。 例如,`List<String>` 和 `List<Integer>` 在运行时实际上都是 `List` 对象。因此,在运行时无法直接获取到类型参数的信息。这...
Java泛型是Java编程语言中的一种重要特性,它允许开发者在编写代码时指定类型参数,从而提高代码的灵活性和可读性。本文将详细介绍Java泛型的用法 及T.class的获取过程解析。 一、泛型的基本概念 泛型是Java 5中...
- **非原始类型的泛型**:不能使用原始类型如`int`作为泛型参数,而应使用其包装类型`Integer`。 #### 总结 泛型是Java语言中的一个重要特性,它不仅提高了代码的灵活性和可重用性,还增强了类型安全性。通过合理...
这意味着所有泛型类型最终都会被转换为非泛型类型。例如,`List<String>`和`List<Integer>`在运行时实际上是相同的类型,都被擦除成了`List`。 ##### 类型擦除的影响 - **静态成员问题**:泛型类中的静态成员无法...
这些约束允许我们指定泛型类型的限制条件,使得某些操作成为可能或者更加高效。 - **泛型类型参数的约束**: - 示例:定义一个泛型链表类 `LinkedList, T>` 其中 `K` 需要实现 `IComparable` 接口: ```csharp ...
尽管Ada、ALGOL68、Eiffel和C++等编程语言早期就支持了与泛型相关的语法特性,但泛型技术并未立即得到广泛应用,直至C++ STL(Standard Template Library)的出现,泛型技术才真正引起了软件开发界的广泛关注和实际...
4. **约束**:可以对泛型类型参数添加约束,限制它可以是什么类型。比如,可以约束`where T : class`表示`T`必须是引用类型,或者`where T : struct`表示`T`必须是值类型,还可以添加继承自某个类或实现某个接口的...