Java之反射


2019/2/1 Java

# Java反射:框架设计的灵魂

设计框架用的,学会能对框架有更好的理解

  • 反射:将类的各个组成部分封装为其他对象,这就是反射机制
    • 好处:
      1. 可以在程序运行过程中,操作这些对象
      2. 可以解耦,提高程序的可拓展性

# 类对象

# 什么是类对象

类对象,就是用于描述这种类,都有什么属性,什么方法的

作用: 从class文件里提取出一个类的成员变量构造方法成员方法(主要) 并将其封装成数组Field[] fieldsConstructor[] consMethod[] methods

# 获取类对象方式

获取类对象有3种方式

  1. Class.forName("全类名") //将字节码文件加载进内存,返回Class对象
    • 全类名,就是包名.类名
    • 多用于配置文件,将类名定义在配置文件中。读取文件,加载类
  2. 类名.class //通过类名的属性class获取
    • 多用于参数的传递
  3. 已经实例对象.getClass() //getClass()在Object类中定义着(换句话说:所有类都这个方法)
    • 多用于对象的获取字节码的方式

在一个JVM中,一种类,只会有一个类对象存在。所以以上三种方式取出来的类对象,都是一样的。 方法示例:

package reflection;

import charactor.Hero;

public class TestReflection {

    public static void main(String[] args) {
            String className = "charactor.Hero";
            try {
                Class pClass1=Class.forName(className);
                Class pClass2=Hero.class;
                Class pClass3=new Hero().getClass();
                System.out.println(pClass1==pClass2);
                System.out.println(pClass1==pClass3);
            } catch (ClassNotFoundException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

# 获取类对象的时候,会导致类属性被初始化

无论什么途径获取类对象,都会导致静态属性被初始化,而且只会执行一次。(除了直接使用 Class c = Hero.class 这种方式,这种方式不会导致静态属性被初始化)

# 类对象功能(即获取类的各个部分)

  1. 获取成员变量们
    • Field[] getFields() :获取所有public修饰的成员变量,包括从父类继承来的变量

    • Field getField(String name) :获取指定名称的public修饰的成员变量,包括从父类继承来

    • Field[] getDeclaredFields() :获取所有的成员变量,不考虑修饰符,但是不能获取继承来的字段

    • Field getDeclaredField(String name) :获取指定名称的成员变量,不考虑修饰符,但是不能获取继承来的字段

  2. 获取构造方法们
    • Constructor<?>[] getconstructors()

    • Constructor<?> getconstructor(类<?>... parameterTypes)

    • Constructor getDeclaredconstructor()

    • Constructor<?>[] getDeclaredconstructors()

  3. 获取成员方法们
    • Method[] getMethods()

    • Method getMethod(String name,类)

    • Method[] getDeclaredMethods()

    • Method getDeclaredMethod(String name,类)

  4. 获取类名
    • String getName()

# 获取类的各个部分之后,进行的操作

  • Field:成员变量

    • 操作
      1. 设置值

        • void set(Object obj,Object value)
      2. 获取值

        • get(Object obj)
      3. 忽略访问权限修饰符的安全检查

        • setAccessible(true) :暴力反射(用于访问和修改private修饰的成员变量的值,对于其他类的部分也能使用)
  • Constructor:构造方法

    • 创建对象:
      • 用获取到的构造器调用newInstance()

      • 如果使用空参数构造方法创建对象,操作可以简化:Class对象的newInstance()方法(Object提供的)

  • Method:方法对象

    • 执行方法

      • Object invoke(Object obj,Object args)
    • 获取方法名称:

      • String getName:获取方法名

Initializing...

山楂树之恋
程佳佳