反射机制

2022-09-14 20:25:36 浏览数 (1)

1、反射概念

反射就是在程序运行的过程中,动态的创建对象。 只要知道该类的类名称,就可以使用它的字节码对象创建该类的一个对象。对于这个类中的任何一个成员或者属性,我们都可以访问或者使用它。

2、Class对象

2.1、什么是字节码文件?

字节码文件,也就是以.class结尾的文件,他是Java中的类经过编译之后生成的字节码数据文件!该文件最终会被JVM加载进内存。

2.2、什么是字节码对象?

前面说过,JVM最终会把字节码文件加载进内存,该文件进JVM内存之后,Java就会把他当做是一个字节码对象!因为Java是一门面向对象的语言,在Java的世界中,所有的东西都是对象,自然也包括该字节码文件了!

2.3、字节码对象的获取方式

(1)Object对象的getClass方法 (2)类型.class属性 (3)Class类的静态方法–>forName()

代码语言:javascript复制
public static void main(String[] args) throws Exception {
		//方式一
		//Object getClass()方法
		Person p = new Person();
		Class clazz1 = p.getClass();
		
		//方式二
	    //类型.class属性
		Class clazz2 = Person.class;
		Class clazz3 = Student.class;
		Class clazz4 = int.class;//基本数据类型也有字节码对象
		
		//方式三
		//Class类的静态方法---> forName("类的完整路径");
    	//注意:这里要用全路径名
		Class clazz5 = Class.forName("Test.Student");  		
    //思考:同一个类的字节码对象,在程序的一次运行过程中会被获取几次?
}

2.4、Class对象的组成

Class对象主要由以下几部分组成:

(1)若干Constructor 对象

(2)若干Method对象

(3)若干Field对象

3、Constructor对象

3.1、Constructor概述

首先思考一个问题,构造器的作用是什么?构造器的作用就是构造一个对象!我们平时用new关键来创建一个类的对象,new后面跟着的其实就该类的构造方法!如下图所示:

构造器是用来构建对象的,同样的,构造器对象/Constructor对象也是用来构建对象的!

代码语言:javascript复制
public class Person {
    private String name;
    private int age;

    public Person() {
    }

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    @Override
    public String toString() {
        return "Person{"  
                "name='"   name   '''  
                ", age="   age  
                '}';
    }
}

3.2、得到构造器对象

(1)公共构造器的获取方法

getConstructors()

代码语言:javascript复制
public static void main(String[] args) throws Exception {
    //获得字节码对象
    Class clazz = Person.class;
    //得到所有公共构造器对象
    Constructor[] constructors = clazz.getConstructors();
    for (Constructor constructor : constructors) {
        System.out.println(constructor);
    }
}

(2)所有构造器的获取方式

getDeclaredConstructors()

代码语言:javascript复制
public static void main(String[] args) throws Exception {
		//获得字节码对象
		Class clazz = Person.class;
		//得到所有公共构造器对象
		Constructor[] constructors = clazz.getDeclaredConstructors();
		for (Constructor constructor : constructors) {
			System.out.println(constructor);
		}
}

(3)获得指定公共构造器

getConstructor(Class… parameter);

代码语言:javascript复制
public static void main(String[] args) throws Exception {
		//获得字节码对象
		Class clazz = Person.class;
		//得到所有公共构造器对象
		Constructor constructor = clazz.getConstructor(String.class,int.class);
//参数是可变形参,参数类型是该参数类型的字节码对象--?Class… parameter
		System.out.println(constructor);
}
代码语言:javascript复制
public static void main(String[] args) throws Exception {
		//获得字节码对象
		Class clazz = Person.class;
		//得到所有公共构造器对象
		Constructor constructor = clazz.getConstructor();
//参数是可变形参,参数类型是该参数类型的字节码对象--?Class… parameter
		System.out.println(constructor);
}

(4)获得指定非公共构造器对象

getDeclaredConstructor(Class… parameter);

代码语言:javascript复制
public static void main(String[] args) throws Exception {
		//获得字节码对象
		Class clazz = Person.class;
		//得到所有公共构造器对象
Constructor constructor = clazz.getDeclaredConstructor(String.class,int.class);
//参数是可变形参,参数类型是该参数类型的字节码对象--?Class… parameter
		System.out.println(constructor);
}
代码语言:javascript复制
public static void main(String[] args) throws Exception {
		//获得字节码对象
		Class clazz = Person.class;
		//得到所有公共构造器对象
		Constructor constructor = clazz.getDeclaredConstructor();
//参数是可变形参,参数类型是该参数类型的字节码对象--Class… parameter
		System.out.println(constructor);
}

3.3、用构造器对象创建该类实例

newInstance(Object… initargs));

4、Method对象

4.1、Method对象的获取

getMethods()—>得到所有公共的方法对象 getDeclaredMethods()-?得到所有的方法对象 getMethod(String name,Class… parameter);得到指定的公共方法对象 getDeclaredMethod(String name,Class… parameter);得到指定的任意方法对象

代码语言:javascript复制
public static void main(String[] args) throws Exception {
		//获得字节码对象
		Class clazz = Person.class;
		//得到所有公共的方法对象
		Method[] methods = clazz.getMethods();
		//得到所有方法对象
		Method[] methods2 = clazz.getDeclaredMethods();
		//得到指定的公共方法对象
		Method method = clazz.getMethod("method", String.class);
		//得到指定的非公共方法对象
		Method method2 = clazz.getDeclaredMethod("method", String.class);
}

4.2、Method对象的使用

invoke(Object obj, Object… args);

代码语言:javascript复制
public static void main(String[] args) throws Exception {
		//获得字节码对象
		Class clazz = Person.class;
		//得到指定的公共方法对象
		Method method = clazz.getMethod("method", String.class);
		//正常调用方法的格式是:对象名.方法名(参数)
		//反射执行方法的格式:方法对象.invoke(方法所属对象,实参列表);
		method.invoke(clazz.newInstance(), "haha");
}

5、Field对象

5.1、获取Field对象

代码语言:javascript复制
public static void main(String[] args) throws Exception {
		//获得字节码对象
		Class clazz = Person.class;
		//得到指定的Field
		Field field = clazz.getField("name");
		System.out.println(field);
		//得到Field对象的值
		System.out.println(field.get(clazz.newInstance()));
}

补充:

​ Class的newInstance方法

​ 底层调用无参的公共的Constructor对象的newInstance方法创建该类的实例

5.2、设置Field对象的值

代码语言:javascript复制
public static void main(String[] args) throws Exception {
		//获得字节码对象
		Class clazz = Person.class;
		//得到指定的Field
		Field field = clazz.getField("name");
		//给指定的Field对象设置值
		Object object = clazz.newInstance();
		field.set(object, "zhangsan");
		//获取值
		System.out.println(field.get(object));		
}

0 人点赞