java运用反射机制能够读取和调用加载到内存中的java程序(Class,Field,Method,Array等)。但是,如果属性或方法使用了泛型来声明数据类型,那么能否读取java程序所指定的泛型具体是什么呢?
在网上看到过一个牛人在百度知道里对一个人的回答,他的意思大概是泛型只在编译的时候用于类型的检查,java程序加载进内存后,泛型就不存在了,而jdk的反射是模拟java运行时的环境读取和调用程序,因此,不能获得泛型的实际类型。牛人告诫道不能把泛型的功能想得太强大了,如果要获得泛型的实际类型,只有在运行时泛型被指定后才能读取。例如如下方法可以读取泛型实例化之后具体是什么类型的,但是该方法只有在java类被实例化之后才能调用。
public class GenericClass<T extends List<Number> >{
private T t;
private List<Contract> contracts;
public Class getActualClass(){
return t.getClass();
}
}
牛人的观点很有道理。再例如,我们在用反射读取调用getDeclaraedMethod的时候,传入的参数类型列表就不能使用泛型。
但是,有时候,比如属性 private List<Contract> contracts;我们就想知道List所指定的泛型是什么,然后才能给contracts属性设置一个vlalue。这时候该怎样读取属性呢?
java的反射机制还有一套Type接口,该接口的实现类和子接口向我们展示了java的泛型在运行时是怎么实现的。访问这些接口可以在运行时读取关于泛型的数据,因此也不能说泛型在运行时就没有了,而是交给其他对象来处理了。
Class类直接实现了Type接口,但是Type的实现类不止一个,换句话说,Class仅仅是Type的一种,如果我们在运行时通过 type instanceof Class 返回true 则可以将type类型强转为Class实例,即 Class cla = (Class)type; 然后就可以用该Class实例构造对象调用方法了。换言之,泛型是class之外的Type,我们只要用反射访问各种Type,直到某个Type被验证是Class类型的,那我们就能找到我们想要的运行时Class了。
那么Class之外,还有有哪些Type呢?这就是我之前一直没有看懂的那些反射api了内容了。
泛型的英文是GenericType 方法的泛型参数是method.getGenericParameterTpe 属性的泛型是 field.getGenericType 这二者都返回Type,不同的仅仅是方法返回的所有参数的Type[],而属性仅仅返回一个Type。此时的type不仅带有Class信息还带有<>里的数据。但是jdk却并没有为Type规定任何方法,唯一的办法是检查Type究竟是哪种子Type种实例,直到找到Class类型的实例为止。所以,要获得泛型的实际类型,要么是递归调用方法,要么是用while循环。
区分泛型声明,使用泛型时传递类型参数,以及引用泛型这三者所指是很有意义的。这三者的区别就相当于是 方法声明的形式参数,调用方法传递实质参数,以及在方法体中用参数名使用某个参数的区别。以上例的GenericClass来说,类名后的T是泛型声明,属性使用的T是泛型引用。而new GenericClAass<Contract> 则时给泛型传递类型参数。GenericClassn内还有List<Number> 这是对给List接口声明的泛型传递类型参数,换言之用在class泛型声明<>里内的内容并不都是泛型声明,泛型声明可以组合其他类型描述自己。
理解了以上的区别,再去看java反射包里那些各种type接口,就省事多了。
还有一点是 泛型中 <>内的 extends包括了implements
一,TypeVariable Type的子接口 实现类是TypeVariableImpl,这个是运行时用来处理泛型声明的。通过 type instenceof TypeVariable 返回true 然后 type = (TypeVariable)type 便可访问该接口提供的三个方法.也可以通过type.getClass() == TypeVariableImpl.class来判断,但是不推荐,因为实现类可能更新。
1,getName():String 返回形式泛型参数的名字 就是T E K 等。
2,Type[] getBounds() 返回泛型声明的上边界类型。如果没有指定 T extends什么,那返回的Type 就是 Object.class。注意1,该方法并不一定返回Class实例,因为泛型的使用可以很复杂,一个泛型声明extedns的对象完全可能又是一个泛型。2,该方法虽然返回的是Type数组,但是经过笔者测试,该方法总是返回一个元素。笔者猜想这或许是考虑到可以返回空数组因此避免返回null(ps:不确定,待高人回答)。
3,只有类(Class) 构造方法(Constractor),方法(Method)才能声明泛型,这三者都是GenericDeclaration的实现类。因此TypeVariable<D extends GenericDeclaration>只能接收GenericDeclarationd的类型参数。 D getGenericDeclaration() 返回声明泛型的对象 即某个Class,Constractor或Method
分享到:
相关推荐
Java反射和泛型是两种强大的编程特性,它们在开发中有着广泛的应用,特别是在数据库操作的动态化场景下。本文将详细介绍如何结合这两种技术实现在Java中对MySQL、SQL Server或Oracle数据库进行动态的增删改查操作。 ...
对java泛型以及反射机制进行原理和应用上的讲解,帮助初学者对这两个概念进行更轻松的掌握
综上所述,这个项目展示了如何利用Java的泛型和反射技术实现一个通用的DAO,使得数据库操作更加灵活和易于维护。泛型确保了类型安全,而反射则提供了运行时的动态行为。这种设计模式在实际开发中非常常见,尤其是在...
Java泛型和反射机制
Java反射是Java语言提供的一种能力,允许运行中的程序动态地获取类的信息(如类名、方法名、参数类型等)并调用这些方法。反射机制的核心类包括`Class`、`Constructor`、`Method`和`Field`,它们分别代表类、构造器...
基于java的开发源码-java多线程反射泛型及正则表达式学习笔记和源码.zip 基于java的开发源码-java多线程反射泛型及正则表达式学习笔记和源码.zip 基于java的开发源码-java多线程反射泛型及正则表达式学习笔记和源码....
总的来说,Java 5 中的泛型和反射这两个特性显著提升了代码的类型安全性和灵活性,同时,反射为解决复杂编程问题提供了新的途径。学习和掌握这两个特性对于深入理解 Java 并编写更高效、安全的代码至关重要。
Java泛型是Java编程语言中的一种重要特性,它允许开发者在编写代码时指定类型参数,从而提高代码的灵活性和可读性。本文将详细介绍Java泛型的用法 及T.class的获取过程解析。 一、泛型的基本概念 泛型是Java 5中...
反射和泛型是一种重要的解决途径。 此代码是一个生成泛型对象的类。 比如: Pool<Point> pool = new Pool(){}; Point p = pool.get(x, y); //在此构造Point对象 ... pool.put(p); 希望能帮助那些为查找泛型构造器、...
Java 5 泛型是Java编程语言中一个重要的里程碑,它引入了类型安全的集合,大大增强了代码的可读性和可维护性。泛型在Java 5中首次亮相,为开发者提供了一种方式来限制集合(如List、Set、Map等)中可以存储的数据...
反射是Java语言的一个特性,它允许程序在运行时获得任何类的内部信息,并且能够操作类或对象的内部属性和方法。通过反射,可以动态地创建对象,调用方法,访问属性,甚至可以解析存储在文件系统中的类定义文件(....
Java试题-3:反射和泛型的综合应用 Java反射 泛型都是比较高级的应用技术
Java反射与泛型是Java编程中的两个重要特性,它们各自为开发者提供了强大的工具来增强代码的灵活性和类型安全性。在本教程中,我们将深入探讨这两个主题,帮助你更好地理解和运用它们。 **Java反射** Java反射机制...
**泛型** 是从Java 5开始引入的一个特性,它为代码提供了类型安全的机制。泛型允许我们在定义类、接口和方法时指定参数类型,从而在编译时进行类型检查,避免了类型转换的麻烦和潜在的ClassCastException。泛型的...
总的来说,"反射泛型完美版分页.rar"提供的解决方案结合了Java的两种强大特性,旨在提供一个高效、灵活且类型安全的分页工具,对于处理大数据量的应用场景尤其有价值。不过,需要注意的是,过度使用反射可能会导致...
Java泛型是Java编程语言中的一个强大特性,它允许我们在定义类、接口和方法时指定类型参数,从而实现代码的重用和类型安全。在Java泛型应用实例中,我们可以看到泛型如何帮助我们提高代码的灵活性和效率,减少运行时...
Java泛型是Java编程语言中一个强大的特性,它允许在定义类、接口和方法时使用类型参数,从而实现参数化类型。泛型的主要目标是提高代码的类型安全性和重用性,减少类型转换的麻烦,并在编译时捕获可能的类型错误。...
Java泛型是Java编程语言中的一个强大特性,它允许在定义类、接口和方法时使用类型参数,从而实现参数化类型。这使得代码更加安全、可读性更强,并且能够减少类型转换的必要。在“java泛型的内部原理及更深应用”这个...