Java> Java核心卷读书笔记 - 反射

目录

反射简介

能够分析类能力的程序成为反射(reflective)。

反射可以用来干什么?
反射经常用于构建库或工具,主要包含以下能力:

  • 运行时分析类的能力;
  • 运行时查看对象,如编写一个toString查看对象属性;
  • 实现通用的数组操作代码;
  • 利用Method对象,类似于C/C++函数指针;

Class类

主要作用:维护Java对象类型信息 -- 程序运行时,Java运行时系统始终为所有对象维护一个被成为运行时的类型标识。该信息跟踪者每个对象所属的类。虚拟机利用运行时类型信息选择相应方法执行。
保存这些维护类型信息的类称为Class。

获取Class类对象

如何获取Class类对象?
有3种方法:

  1. 对象的getClass()方法;
  2. Class静态方法Class.forName();
  3. 类名.class;

示例:

// 方法1: 一个类的对象 -> Class类对象
Employee e;
Class c = e.getClass(); // 通过getClass(), 获取对象e的类型信息

// 方法2: 类名称: -> Class 类对象
String className = "java.util.Random"; // 类名(需要包含包的路径)
Class c2 = Class.forName(className) ;  // 通过Clas静态方法forName(),

// 方法3: 类名.class -> Class类对象
Class random = Random.class;
Class cint = int.class;
Class cdoubles = Double[].class;

Class类包含哪些类的信息?

  1. 类名;
  2. 创建类的实例;
  3. 比较类型信息;

读取类名

Class的getName方法可以读取类名,包也作为类名的一部分

System.out.println(e.getClass.getName() + " " + e.getName()); 

创建类的实例

Class对象的newInstance方法

// 根据不同获取Class对象方式, 分为三种方式, 不过都是调用Class对象的newInstance方法
// 方式一
Employee e = new Employee();
e.getClass().newInstance();

// 方式二
String s = "java.util.Random";
Object m = Class.forName(s).newInstance();

// 方式三
Object m = Integer.class.newInstance();

比较类型信息"=="

类似于Ojective-C的内省方法,可以用 “==”检查某个类对象是否为指定类对象。
如,

// 检查e的Class对象是否为Employee类对象
Employee e;
if(e.getClass() == Employee.class) {
      ..
}
// 检查e的父对象是否为Object类对象
Employee e;
Class cl = e.getClass();
Class supercl = cl.getSupperClass();

if (supercl == Object.class) {
      // process e or cl
}

捕获异常

如果类名对应类不存在,用forName()创建Class对象会抛出异常ClassNotFoundException。简单处理方式,如下

try {
      Claass c1 = Class.forName("TestNotExistClass");
      // do sth. with c1
}catch(Exception e) {
      e.printStackTrace();
}

反射分析类

  1. 字段类:Field,提供有关类或接口的单个字段的信息,以及对它的动态访问权限。反射的字段可能是一个类(静态)字段或实例字段。;
  2. 方法类:Method;
  3. 构造器类:Constructor;
  4. 修饰符工具类:Modifiers;

Field 字段类型类, Method 方法类型类, Constructor 构造器类

java.lang.reflect包有三个类Field、Method、Constructor分别用于描述类的域(字段)、方法、构造器。
三个类都有getName()方法,返回项名称。
Field类有getType方法,返回域所属类型的Class对象。
Method类和Constructor类有能够报告参数类型的方法。
Method类getReturnType方法能报告函数返回值类型。

Class常用方法

Field[] getFields(); // 返回包含Field对象的数组,记录了类或其超类的公有域
Field[] getDeclaredFields();  // 返回包含Field对象的数组,记录了类的所有域(不包括超类)

Method[] getMethods(); // 返回包含Method对象的数组,记录了类或其超类的公有方法
Method[] getDeclaredMethods();  // 返回包含Method对象的数组,记录了类的所有方法(不包括超类)

Constructor[] getConstructors(); // 返回包含Constructor对象的数组,记录了类或其超类的公有构造器
Constructor[] getDeclareConstructor(); // 返回包含Constructor对象的数组,记录了类的所有构造器(不包括超类)

Class getClass(); // 获取对象或者类的Class对象
Class getSuperclass(); // 获取对象或者类的父类Class对象
Class getName(); // 获取对象或类的名称(字符串)
static Class forName(String); // 根据路径创建Class对象

TypeVariable[] getTypeParameters(); // 获取声明的变量类型的数组

int getModifiers(); // 获取对象或类的的Java语言修饰符(如public, static)使用情况

Field、Method、Constructor常用方法

Class getType(); (Field独有) // 获取域的类型
Class getReturnType(); (Method独有) // 获取返回值类型
Class[] getExceptionTypes(); (Constructor和Method类中) // 描述方法抛出的异常类型数组
Class[] getParameterTypes(); (Constructor和Method类中) // 描述参数类型的Class对象数组
Object get(Object obj); // 获取obj对象中Field对象表示的值, 调用对象是Field对象(即要获取的属性),obj对象是要查询的属性值所属类对象. 也就是说,返回obj.调用对象的Field值
void set(Object obj, Object newValue); // 设置obj.调用对象所属Field = newValue

Class getDeclaringClass(); // 返回用于描述类中定义的Constructor、Method或Field的类型
Class getName(); // 获取名称
int getModifiers(); // 获取修饰符使用情况
void setAccessible(boolean ); // 修改反射对象的访问标志 (为调试、持久存储和相似机制提供的功能)
boolean isAccessible(); // 查询反射对象可访问标志

Modifiers 修饰符工具类

Field、Method、Constructor三个类都有getModifiers方法,返回一个整型值,不同的位代表public static等修饰符使用情况。
可以利用java.lang.reflect包中的Modifier类的静态分析getModifiers返回的整型值,如使用Modifier类的isPublic、isPrivate、isFinal判断方法或构造器是否是public、private或final。
Modifiers.toString() 将修饰符打印出来。

获取Field, Method, Constructor
Class类的getFields、getMethods和getConstructors方法返回类的public 域、方法和构造器数组。(所有的public成员,包括超类的public成员)
Class类的getDeclareFields、getDeclareMethods、getDeclareConstructorsf方法返回类类的所有域、方法和构造器数组。(所有的public、private、protected成员,但不包括超类的成员)

Modifiers 常用方法

static String toString(int modifiers); // 读取modifilers中设置的修饰符使用情况的字符串表示
// 读取是否为函数名对应修饰符修饰
static boolean isAbstract(int modifiers); 
static boolean isFinal(int modifiers);
static boolean isInterface(int modifiers);
static boolean isNative(int modifiers);
static boolean isPrivate(int modifiers);
static boolean isProtected(int modifiers);
static boolean isPublic(int modifiers);
static boolean isStatic(int modifiers);
static boolean isStrict(int modifiers);
static boolean isSynchronized(int modifiers);
static boolean isVolatile(int modifiers);
上一篇:[Usaco2017 Jan]Promotion Counting


下一篇:[01][01][04][01] setAccessible方法