目录
1.介绍
1.1使用反射
反射提供了检测调节运行在jvm上的应用的运行时行为的能力
反射是非常强力的功能并且可以令应用执行不可能的操作。
反射的常见应用:
- 反射机制允许应用可以使用外部的用户自定义的类,即利用它们的完整限定名称创建扩展对象。
- 反射机制可以用于构建类浏览器实现列举类成员。
- 类型信息可以通过反射获得,一次帮助开发者编写正确代码。
- 反射可以检查类的私有成员。
- 反射可以系统地调用定义在类中的可发现的API集合。
1.2反射的缺点
反射框架十分强力,但是不能随意使用。
如果不适用反射框架就能达成操作,那最好就不要使用反射。
性能开销
由于反射涉及动态解析类型,一些jvm的优化不会执行。
安全限制
反射框架需要运行时权限,但有些SecurityManager不会授权。
内部暴露
反射可以执行非反射代码的非法功能,例如,方位private域与方法。
这样破坏了封装性,将可能产生代码行为混乱以及破坏移植性。
反射破坏了抽象性,所以,当平台升级时,代码行为可能发生改变。
2.Class
对每一种类型的对象,JVM都实例化一个java.lang.Class的不可变实例。
Class提供了检测对象运行时属性(即对象的成员与方法)的方法。
Class提供了创建新类与对象的能力。
Class类是Reflection框架的进入点。
2.1遍历类对象
所有反射操作的进入点都是java.lang.Class。
除了ReflectPermission类,其余java.lang.reflect中的类都不具有public构造器。
可以通过对象、类名称、类型、存在的Class来获取Class对象。
Object.getClass()
Class c = "fff".getClass();
note:获取String对象"fff"的Class对象。
ps:只有继承Object的对象,才能以这种方式获取Class。
ps:对接口对象使用getClass,获取实现类对象。
语法.class
Class c = boolean.class;
note:获取boolean的Class。
Class c = int[][][].class;
note:获取多维数组的Class。
Class.forName()
Class c = Class.forName("examples.Foo");
note:通过完整类名examples.Foo获取Foo的Class类。
ps:静态方法Class.forName()通过使用完整类名获取对应的Class。
如果Class表示的是数组,数组类型名称的内部形式需要在元素类型名称之前放置一个或多个'['用以表示嵌套数组的深度。
Class c = Class.forName("[[[[I");
note:等价于int[][][][].class。
原始类型包装者的TYPE域
wrapper将原始类型包装为引用类型。
Class c = Double.TYPE;
Class c = Void.TYPE;
note:第一个Class与doubel.class等价,第二个Class与void.class等价。
返回Class对象的方法
可以通过反射框架APIs提供的一些方法返回Class对象。
Class.getSuperclass()
Class c = javax.swing.JButton.class.getSuperclass();
note:获取javax.swing.JButton的父类的Class。
Class.getClasses()
Class<?>[] c = Character.class.getClasses();
note:获取Character内定义的所有的类与接口(即public内部类与接口)的Class,包括继承的内部类与接口。
Class.getDeclaringClasses()
获取内部定义的类与接口(不一定是public)的Class,匿名内部类不算,继承的内部类也不算。
Class.getDeclaringClass()
如果给定Class是内部类或接口,返回定义了它的类的Class对象,如果不是内部类或接口,返回null。
java.lang.reflect.Field.getDeclaringClass():获取声明了此域的类的Class对象。
java.lang.reflect.Method.getDeclaringClass():获取声明了此方法的类的Class对象。
java.lang.reflect.Constructor.getDeclaringClass():获取声明了此构造器的类的Class对象。
Class.getEnclosingClass()
获取封闭类的Class对象,可以用于获取匿名内部类的封闭类。
2.2检测类修饰符与类型
java.lang.reflect.Modifier包含了所有可能的修饰符的声明。
Modifier用于解析Class.getModifiers()返回的修饰符集合。
获取类名称
c.getCanonicalName();
note:获取Class对象c表示的类的名称。
获取修饰符
Modifier.toString(c.getModifiers());
note:获取Class对象c表示的类的所有修饰符。
ps:所有接口都会被jvm设置为abstract。
获取类型参数名
TypeVariable[] tv = c.getTypeParameters();
note:获取Class对象c表示的类定义的类型参数名。
获取实现的接口
Type[] intfs = c.getGenericInterfaces();
note:获取Class对象c表示的类实现的所有接口。
获取持有的注解
Annotation[] ann = c.getAnnotations();
note:获取Class对象c表示的类持有的所有注解。
ps:只有java.lang.annnotation.RetentionPolicy设置为RUNTIME的注解才可以被访问。
获取父类
Class<?> ancestor = c.getSuperclass();
note:获取Class对象c表示的类的父类。
ps:原始类型与Object返回null。
ps:数组返回Object。
2.3发现类成员
获取包名
Package p = c.getPackage();
获取构造器
Constructor[] cs = c.getConstructors();
获取域
Field[] fs = c.getFields();
ps:java.lang.reflect.Field.isEnumConstant()用于判断域是否为常量。
获取方法
Method[] ms = c.getMethods();
获取内部类
Class[] ccs = c.getClasses();
获取成员
Member[] mes = c.getFields();
note:使用Member代表域。
ps:Member可以代表域、方法、构造器。
ps:Member没有包含getGenericString()方法,使用时可以将其转型。