thinking in java反射

Posted five five open

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了thinking in java反射相关的知识,希望对你有一定的参考价值。

前言

反射是框架设计的灵魂,使用的前提条件:必须先得到字节码的Class,Class类用于表示字节码,字节码即是.class文件

概述

JAVA反射机制:在程序运行的过程中,对于任意一个类,都可以知道这个类的所有信息,比如:成员变量、方法、构造方法、包等信息;要想用反射机制,首先要获取到

该类的字节码文件对象Class,然后用Class类中的方法把各种成分映射成Java对象,关于.class文件,在我们new对象的时候,本地IDE自动编译,然后jvm会自动的从硬盘

读取到.class文件,并创建一个该类的Class文件,但是,如果我们new了多个该类的实例,内存中只会有一份该类的字节码文件。

API

Class 类与 java.lang.reflect 类库一起对反射的概念进行了支持,该类库包含了 Field、Method、Constructor 类 (每个类都实现了 Member 接口)该接口反映单个成员(字段

或方法)或构造方法的标识信息,正因为实现了该接口,因此可以反射相关变量、方法信息,这些类型的对象时由 JVM 在运行时创建的,用以表示未知类里对应的成员。

反射

获取字节码

在 Java 中可以通过三种方法获取类的字节码 (Class) 对象,如下:

技术分享图片
package com.oxygen.bean;

public class ReflectTest {
    public static void main(String[] args) throws ClassNotFoundException {
        Student student = new Student();
        Class<?> clazz1 = student.getClass(); //方式1
        Class<?> clazz2 = Student.class; //方式2
        Class clazz3 = Class.forName("com.oxygen.student");//方式3
    }
}
View Code

获取类信息

Student类如下

技术分享图片View Code

1. 通过构造函数对象Constructor创建对应类的实例

技术分享图片
package com.oxygen.bean;

import java.lang.reflect.Constructor;

public class ReflectTest {
    public static void main(String[] args) throws Exception {
        Student student = new Student(); //Student的带参构造函数依赖另外一个类Car
        Class<?> clazz1 = student.getClass(); //方式1
        func1(clazz1); //通过无参构造函数反射Student实例
        func2(clazz1);//通过有参构造函数反射Student实例
        func3(clazz1);//获取所有的构造函数反射Student实例
        func4(clazz1); // 反射私有构造函数
    }

    private static void func4(Class<?> clazz1) throws Exception {
        Constructor<?> declaredConstructor = clazz1.getDeclaredConstructor(String.class);
        declaredConstructor.setAccessible(true);//设置为可以访问
        System.out.println(declaredConstructor.newInstance("zhangsan"));
    }

    private static void func3(Class<?> clazz1) throws Exception {
        Constructor<?>[] constructors = clazz1.getDeclaredConstructors();
        for (Constructor<?> constructor : constructors) {
            System.out.println("func3: " + constructor);
        }
    }

    /**
     * 因为Student的带参构造函数依赖另外一个类Car,因为必须保证JVM能获取到Car的字节码
     * @param clazz1
     * @throws Exception
     */
    public static void func2(Class<?> clazz1) throws Exception {
        Car car = new Car();//保证
        Constructor<?> constructor = clazz1.getConstructor(String.class, Integer.class, Car.class);
        Student student = (Student) constructor.newInstance("张三", 18, new Car());
        System.out.println(student);
    }

    public static void func1(Class<?> clazz1) throws Exception {
        Constructor<?> constructor = clazz1.getConstructor();
        Student student = (Student) constructor.newInstance();
        System.out.println(student);
    }
}
View Code

2. 获取成员方法

技术分享图片
package com.oxygen.bean;

import java.lang.reflect.Constructor;
import java.lang.reflect.Method;

public class ReflectTest {
    public static void main(String[] args) throws Exception {
        Student student = new Student();
        Class<?> clazz1 = student.getClass();
        m1(clazz1);
        m2(clazz1);
        m3(clazz1);
        m4(clazz1);
    }

    /**
     * 获取所有的方法,包括私有的,不包括继承Object类的9个方法
     * @param clazz1
     */
    public static void m4(Class<?> clazz1) {
        Method[] declaredMethods = clazz1.getDeclaredMethods();
    }

    /**
     * 获取所有的”公有“方法,包括继承Object类的9个方法
     * @param clazz1
     */
    public static void m3(Class<?> clazz1) {
        Method[] methods = clazz1.getMethods();
    }

    /**
     * 获取私有的show4()方法
     * @param clazz1
     * @throws Exception
     */
    public static void m2(Class<?> clazz1) throws Exception {
        Method method;
        method = clazz1.getDeclaredMethod("show4", int.class);
        Student stu = func1(clazz1); // 实例化一个Student对象
        method.setAccessible(true);
        method.invoke(stu, 20);//反射私有方法show4(),第一个参数是实例,第二个参数是被反射方法的参数
    }

    /**
     * 获取公有的show1()方法
     * @param clazz1
     * @throws Exception
     */
    public static void m1(Class<?> clazz1) throws Exception {
        Method method = clazz1.getMethod("show1", String.class); //第一个参数是方法名称,第二个参数是形参类型
        Student stu = func1(clazz1); // 实例化一个Student对象
        method.invoke(stu, "lisi"); //反射公有方法show1(),第一个参数是实例,第二个参数是被反射方法的参数
    }

    public static Student func1(Class<?> clazz1) throws Exception {
        Constructor<?> constructor = clazz1.getConstructor();
        Student student = (Student) constructor.newInstance();
        return student;
    }
}
View Code

以上是关于thinking in java反射的主要内容,如果未能解决你的问题,请参考以下文章

Thinking in Java读书笔记2

Thinking in Java 整理笔记:类型信息

Thinking in Java 整理笔记:类型信息

Thinking in java Chapter19 枚举类型

Thinking in Annotation

Thinking in Java