Java反射

Java 反射!

一、类的加载

  当程序要使用某个类时,如果该类还未被加载到内存中,则系统会通过加载,连接,初始化三步来实现对这个类进行初始化。

  • 加载
    指将class文件读入内存,并为之创建一个Class对象。
    任何类被使用时系统都会建立一个Class对象。

  • 连接
    验证 是否有正确的内部结构,并和其他类协调一致。
    准备 负责为类的静态成员分配内存,并设置默认初始化值。
    解析 将类的二进制数据中的符号引用替换为直接引用。

  • 初始化

二、类的初始化时机

  • 创建类的实例
  • 类的静态变量,或者为静态变量赋值
  • 类的静态方法
  • 使用反射方式来强制创建某个类或接口对应的java.lang.Class对象
  • 初始化某个类的子类
  • 直接使用java.exe命令来运行某个主类

三、三种类的加载器

  负责将.class文件加载到内在中,并为之生成对应的Class对象。

  • Bootstrap ClassLoader 根类加载器
    也被称为引导类加载器,负责Java核心类的加载
    比如System, String等。在JDK中JRE的lib目录下rt.jar文件中

  • Extension ClassLoader 扩展类加载器
    负责JRE的扩展目录中jar包的加载。
    在JDK中JRE的lib目录下ext目录

  • System ClassLoader 系统类加载器
    负责在JVM启动时加载来自java命令的class文件,以及classpath环境变量所指定的jar包和类路径。

四、反射的概念及作用

  JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。

  要想解剖一个类,必须先要获取到该类的字节码文件对象。而解剖使用的就是Class类中的方法.所以先要获取到每一个字节码文件对应的Class类型的对象。

五、class文件的产生过程

  Class 没有公共构造方法。Class 对象是在加载类时由 Java 虚拟机以及通过调用类加载器中的 defineClass 方法自动构造的。

六、获取class文件对象的三种方式

  • 通过Object类中的getObject()方法

    1
    2
    Test t = new Test();
    Class c = t.getClass();
  • 通过 类名.class 获取到字节码文件对象(任意数据类型都具备一个class静态属性)

    1
    Class c = Test.getClass();
  • 通过Class类中的方法(将类名作为字符串传递给Class类中的静态方法forName)。

    1
    Class c3 = Class.forName("com.ccblogs.reflect.Test");

三种方法的区别:

  前两种你必须明确Person类型。


  第三种是指定这种类型的字符串,按照配置文件加载。

七、反射获取空参构造方法并运行

  • ComboListTest.java文件:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    import java.lang.reflect.Constructor;
    public class ComboListTest {
    @SuppressWarnings({ "rawtypes", "unchecked" })
    public static void main(String[] args) throws Exception {
    Class c = Class.forName("com.ccblogs.inflect.ComboList");
    // 获取class文件对象中所有公共的构造方法
    Constructor[] cons = c.getConstructors();
    for (Constructor con : cons) {
    System.out.println(con);
    }
    // 运行类中的空参构造方法
    Constructor con = c.getConstructor();
    Object obj = con.newInstance();
    System.out.println(obj);
    }
    }
  • ComboList.java文件:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    public class ComboList {
    public ComboList() {
    System.out.println("无参构造方法");
    }
    public ComboList(String str, int iNum) {
    System.out.println("有参构造方法:" + str + ", " + iNum);
    }
    private String key;
    private String value;
    public String getKey() {
    return key;
    }
    public void setKey(String key) {
    this.key = key;
    }
    public String getValue() {
    return value;
    }
    public void setValue(String value) {
    this.value = value;
    }
    }

八、反射获取有参数构造方法并运行

  • ComboListTest.java文件:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    import java.lang.reflect.Constructor;
    public class ComboListTest {
    @SuppressWarnings({ "rawtypes", "unchecked" })
    public static void main(String[] args) throws Exception {
    Class c = Class.forName("com.ccblogs.inflect.ComboList");
    // 获取class文件对象中有参构造方法并运行
    Constructor con = c.getConstructor(String.class, int.class);
    con.newInstance("11", 2);
    }
    }
  • ComboList.java文件:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    public class ComboList {
    public ComboList() {
    System.out.println("无参构造方法");
    }
    public ComboList(String str, int iNum) {
    System.out.println("有参构造方法:" + str + ", " + iNum);
    }
    private String key;
    private String value;
    public String getKey() {
    return key;
    }
    public void setKey(String key) {
    this.key = key;
    }
    public String getValue() {
    return value;
    }
    public void setValue(String value) {
    this.value = value;
    }
    }

九、反射获取构造方法并运行的快速方法

  • ComboListTest.java文件:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    public class ComboListTest {
    @SuppressWarnings({ "rawtypes" })
    public static void main(String[] args) throws Exception {
    Class c = Class.forName("com.ccblogs.inflect.ComboList");
    // Class类中定义方法,T newInstance()直接创建被反射类的对象实例
    // 快捷方式获取无参构造函数,被反射的类必须有无参构造函数,且该构造函数是public
    Object obj = c.newInstance();
    System.out.println(obj);
    }
    }
  • ComboList.java文件:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    public class ComboList {
    public ComboList() {
    System.out.println("无参构造方法");
    }
    public ComboList(String str, int iNum) {
    System.out.println("有参构造方法:" + str + ", " + iNum);
    }
    private String key;
    private String value;
    public String getKey() {
    return key;
    }
    public void setKey(String key) {
    this.key = key;
    }
    public String getValue() {
    return value;
    }
    public void setValue(String value) {
    this.value = value;
    }
    }

十、反射获取私有构造方法并运行

  不推荐,破坏封装性和安全性。

  • ComboList.java文件:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    public class ComboList {
    public ComboList() {
    System.out.println("无参构造方法");
    }
    public ComboList(String str, int iNum) {
    System.out.println("有参构造方法:" + str + ", " + iNum);
    }
    @SuppressWarnings("unused")
    private ComboList(int iNum, String str) {
    }
    private String key;
    private String value;
    public String getKey() {
    return key;
    }
    public void setKey(String key) {
    this.key = key;
    }
    public String getValue() {
    return value;
    }
    public void setValue(String value) {
    this.value = value;
    }
    }
  • ComboListTest.java文件:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    import java.lang.reflect.Constructor;
    public class ComboListTest {
    @SuppressWarnings({ "rawtypes", "unchecked" })
    public static void main(String[] args) throws Exception {
    Class c = Class.forName("com.ccblogs.inflect.ComboList");
    Constructor con = c.getDeclaredConstructor(int.class, String.class);
    con.setAccessible(true);
    Object obj = con.newInstance(12, "34");
    System.out.println(obj);
    }
    }

十一、反射获取成员变量并改值

  • ComboList.java文件:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    public class ComboList {
    public ComboList() {
    System.out.println("无参构造方法");
    }
    public ComboList(String str, int iNum) {
    System.out.println("有参构造方法:" + str + ", " + iNum);
    }
    @SuppressWarnings("unused")
    private ComboList(int iNum, String str) {
    }
    public String key;
    public String value;
    public String getKey() {
    return key;
    }
    public void setKey(String key) {
    this.key = key;
    }
    public String getValue() {
    return value;
    }
    public void setValue(String value) {
    this.value = value;
    }
    }
  • ComboListTest.java文件:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    import java.lang.reflect.Constructor;
    public class ComboListTest {
    @SuppressWarnings({ "rawtypes" })
    public static void main(String[] args) throws Exception {
    Class c = Class.forName("com.ccblogs.inflect.ComboList");
    Field field = c.getField("key");
    Object obj = c.newInstance();
    field.set(obj, "keyId");
    System.out.println(obj);
    }
    }

十二、反射获取空参数成员方法并运行

  • ComboList.java文件:

    1
    2
    3
    4
    5
    6
    7
    8
    public class ComboList {
    public void setKey() {
    System.out.println("setKey********");
    }
    public void setValue(String value) {
    System.out.println("setValue********" + value);
    }
    }
  • ComboListTest.java文件:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    import java.lang.reflect.Method;
    public class ComboListTest {
    @SuppressWarnings({ "rawtypes", "unchecked" })
    public static void main(String[] args) throws Exception {
    Class c = Class.forName("com.ccblogs.inflect.ComboList");
    Object obj = c.newInstance();
    Method method = c.getMethod("setKey");
    method.invoke(obj);
    }
    }

十三、反射获取有参数的成员方法并运行

  • ComboList.java文件:

    1
    2
    3
    4
    5
    6
    7
    8
    public class ComboList {
    public void setKey() {
    System.out.println("setKey********");
    }
    public void setValue(String value) {
    System.out.println("setValue********" + value);
    }
    }
  • ComboListTest.java文件:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    import java.lang.reflect.Method;
    public class ComboListTest {
    @SuppressWarnings({ "rawtypes", "unchecked" })
    public static void main(String[] args) throws Exception {
    Class c = Class.forName("com.ccblogs.inflect.ComboList");
    Object obj = c.newInstance();
    Method method = c.getMethod("setValue", String.class);
    method.invoke(obj, "kkkkkkkkkkkkk");
    }
    }

十四、反射泛型擦除

  • ComboListTest.java文件:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    import java.lang.reflect.Method;
    import java.util.ArrayList;
    public class ComboListTest {
    @SuppressWarnings({ "unchecked", "rawtypes" })
    public static void main(String[] args) throws Exception {
    ArrayList<String> arrayList = new ArrayList<String>();
    arrayList.add("a");
    Class c = arrayList.getClass();
    Method method = c.getMethod("add", Object.class);
    method.invoke(arrayList, 1);
    method.invoke(arrayList, 2);
    System.out.println(arrayList);
    }
    }

十五、反射通过配置文件运行

  1. 工程下创建文件Config.properties。

    1
    2
    className=com.ccblogs.inflect.ComboList
    methodName=setValue
  2. ComboList.java文件:

    1
    2
    3
    4
    5
    6
    7
    8
    public class ComboList {
    public void setKey() {
    System.out.println("setKey********");
    }
    public void setValue(String value) {
    System.out.println("setValue********" + value);
    }
    }
  3. ComboListTest.java文件:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    import java.io.FileReader;
    import java.lang.reflect.Method;
    import java.util.Properties;
    public class ComboListTest {
    @SuppressWarnings({ "unchecked", "rawtypes" })
    public static void main(String[] args) throws Exception {
    FileReader fr = new FileReader("Config.properties");
    Properties pr = new Properties();
    pr.load(fr);
    fr.close();
    String className = pr.getProperty("className");
    String methodName = pr.getProperty("methodName");
    Class c = Class.forName(className);
    Object obj = c.newInstance();
    Method method = c.getMethod(methodName, String.class);
    method.invoke(obj, "123");
    }
    }