Java反射框架(一)——介绍、Class类

目录

1.介绍

1.1使用反射

1.2反射的缺点

2.Class

2.1遍历类对象

2.2检测类修饰符与类型

2.3发现类成员

翻译源:Java toturial 反射篇


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()方法,使用时可以将其转型。



翻译源:Java toturial 反射篇

猜你喜欢

转载自blog.csdn.net/qq_32165041/article/details/82695859