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));
}