Skip to content

Latest commit

 

History

History
executable file
·
181 lines (86 loc) · 4.29 KB

File metadata and controls

executable file
·
181 lines (86 loc) · 4.29 KB

Java反射机制

1. 概念

Java的反射机制是指在运行中,对于任意一个类(class文件),都能够知道这个类的属性和方法。对于任意一个对象,都能够调用它的任意一个方法和属性,这种动态获取信息,以及动态调用对象的方法的功能称为反射机制。

即动态获取类中的信息,就是Java的反射机制。

对象.属性或者对象.方法就是静态获取类中的信息。

  • 字节码文件

    字节码文件在内存中也是以对象的形式存在的,它的类型就是class

    class:是一个类的描述符,用来描述类的特征

2. 获取字节码文件

  • 获取字节码文件的第一种方式 利用Object类中的getClass()方法,想用这种方式,必须要明确具体的类,创建对象

    Person p = new Person();
    Class clazz = p.getClass();  // p对应的字节码文件
  • 获取字节码文件的方式二 任何数据类型都具备一个静态属性---class,该属性可以获取对应的.class对象。这种方式相对简单,但是还需要明确到类中的静态成员,扩展性不是很强。

    Class clazz = Person.class;
  • 获取字节码文件的方式三 只要通过给定类的字符串名称,就可以获取该类对应的字节码文件对象,这种方式更为扩展。可以利用Class类中的forName()方法完成。这种方式只需要名称即可,更为方便,更为扩展

    Class clazz = Class.forName("reflect.Person");  // 类名全称,包括包名

3. 访问构造器

利用Class类中的forName()方法获得字节码文件对象

// 获取字节码文件
String className = "reflect.Person";
Class clazz = Class.forName(className);

3.1 调用无参构造器

直接利用Class类中的newInstance()方法

// 如何产生该类的对象
Object obj = clazz.newInstance();  // 直接可以使用无参构造器创建对象,返回Object,这儿的obj就是一个Person对象

3.2 调用有参构造器

利用Class类中getConstrunctor()获得一个有参构造器对象,然后利用该构造器创建对象

Constructor constructor = clazz.getConstructor(int.class, String.class);  // 返回的是一个构造器对象
// 利用该构造器创建对象
Object obj = constructor.newInstance(23, "旺财");

3.3 访问字段(设置值和获取值)

// getField获取的是公有的字段
Field  field = clazz.getField("age");
// 获取该字节码文件对象中所有权限修饰的字段
Field field = clazz.getDeclaredField("age");

获取到字段之后,还需要借助对象才可以访问字段的值。由于字段的访问权限问题,所有有以下几种情况

// 1. 访问公有字段
Object obj = clazz.newInstance();
Object o = field.get(obj);  // 获取obj对象中的field字段,返回一个Object
// 2. 访问私有字段
field.setAccessible(true);  // 对私有的字段的访问权限取消检查(暴力访问),不建议使用
Object obj = clazz.newInstance();
Object o = field.get(obj);  // 获取obj对象中的field字段,返回一个Object
// 设置值
field.set(obj, value);  // value是要设置的值

3.4 访问方法

  • 获取所有的公共(public)方法,包括父类中的方法也会获取

    Method[] methods = clazz.getMethods();
  • 只获取该类中的自定义的所有的方法(包括私有的),不包括父类的

    Method[] methods = clazz.getDeclaredMethods();
  • 获取一个无参的方法(获取show()方法),无法获得私有的方法

    Method method = clazz.getMethod("show", null);  // null表示该方法(show())是无参方法
    // 运行方法,需要依赖于对象
    Object obj = clazz.newInstance();
    method.invoke(obj, null);
  • 获取一个有参的方法(获取paramMethod(String name, int age)方法),无法获得私有的方法

    Method method = clazz.getMethod("paramMethod", String.class, int.class);
    Object obj = clazz.newInstance();
    method.invoke(obj, "旺财", 52);