目录
什么是反射
反射允许对封装类的字段,方法和构造函数的信息进行编程访问,即
反射允许对成员变量,成员方法和构造方法的信息进行编程访问
首先要先获取class字节码对象,在根据这个对象获取字段对象(Field)、构造对象(Constructor)、方法对象(Method)
反射的作用:
1、获取一个类里面所有的信息,获取到了之后,在执行其他的业务逻辑
2、结合配置文件,动态的创建对象并调用方法
一、获取class对象的三种方法
1、Class.forName("全类名");使用场景:源代码阶段
全类名=包名+类名
获取全类名的方式:选中类名,右键单击,选择Copy-----Copy Reference
2、类名.class; 加载阶段
3、对象.getClass(); 运行阶段
public static void main(String[] args) throws ClassNotFoundException {
//1、第一种方式
//最为常用
Class clazz1 = Class.forName("exam.Student");
//2、第二种方式
//一般更多的是当做参数进行传递
Class clazz2 = Student.class;
//3、第三种方式
//当已经有了这个类的对象时,才可以使用
Student s = new Student();
Class clazz3 = s.getClass();
}
二、利用反射获取构造方法
获取构造方法
Class类中用于获取构造方法的方法
Constructor<?>[] getConstructors():返回所有公共构造方法对象的数组
Constructor<?>[] getDeclaredConstructor():返回所有构造方法对象的数组
Constructor<T> getConstructor(Class<?>... parameterTypes):返回单个公共构造方法对象
Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes):返回单个构造方法对象
package exam;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Parameter;
public class Test1 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException {
//1、获取class字节码文件对象
Class clazz1 = Class.forName("exam.Student");
//2、获取构造方法
//获取所有公共构造方法
Constructor[] cons1 = clazz1.getConstructors();
for(Constructor con : cons1){
System.out.println(con);
}
System.out.println("-----------------");
//获取所有构造方法(包括私有、受保护的)
Constructor[] cons2 = clazz1.getDeclaredConstructors();
for (Constructor constructor : cons2) {
System.out.println(constructor);
}
System.out.println("-------------------");
//获取单个公共构造方法
//获取无参构造方法
Constructor con = clazz1.getConstructor();
System.out.println(con);
System.out.println("-------------------");
//获取带参的公共构造方法
Constructor constructor = clazz1.getConstructor(String.class,int.class,String.class,String.class);
System.out.println(constructor);
//获取单个构造方法
Constructor constructor1 = clazz1.getDeclaredConstructor(String.class);
System.out.println("---------------");
System.out.println(constructor1);
//获取构造方法的权限修饰符,返回的是修饰符对应的数字
int modifiers = constructor1.getModifiers();
System.out.println(modifiers);
//获取构造方法的参数
Parameter[] parameters = constructor1.getParameters();
for (Parameter parameter : parameters) {
System.out.println(parameter);
}
//创建对象
Student stu = null;
try {
stu = (Student) constructor.newInstance("张三",22,"202001","软件工程");
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
System.out.println(stu);
}
}
创建对象
Constructor类中用于创建对象的方法
注意:
如果是私有的构造方法,需要在创建对象前,使用setAccessible(true)临时取消访问权限检测。
T newlnstance(Object...initargs):根据指定的构造方法创建对象 setAccessible(boolean flag):设置为true,表示取消访问检查
获取修饰符
获取构造方法的权限修饰符,返回的是修饰符对应的整数
//获取构造方法的权限修饰符,返回的是修饰符对应的数字 int modifiers = constructor1.getModifiers(); System.out.println(modifiers);
获取参数
//获取构造方法的参数 Parameter[] parameters = constructor1.getParameters(); for (Parameter parameter : parameters) { System.out.println(parameter); }
三、利用反射获取成员变量
获取成员变量
Class类中用于获取成员变量的方法
Field[] getFields():返回所有公共成员变量对象数组 Field[] getDeclaredFields():返回所有成员变量对象的数组 Field getField(String name):返回单个公共成员变量对象 Field getDeclaredField(String name):返回单个成员变量对象
用法和上面构造方法一样
Field类中用于创建对象的方法
void set(Object obj,Object value):赋值 Object get(Object obj):获取值
package exam;
import java.lang.reflect.Field;
public class Test1 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException {
//1、获取class字节码文件对象
Class clazz1 = Class.forName("exam.Student");
//获取所有公共成员变量
Field[] fields = clazz1.getFields();
for (Field field : fields) {
System.out.println(field);
}
//获取单个成员变量
Field majorField = clazz1.getDeclaredField("major");
System.out.println(majorField);
//获取权限修饰符
int modifiers = majorField.getModifiers();
System.out.println(modifiers);
//获取成员变量类型
Class type = majorField.getType();
System.out.println(type);
//获取成员变量的值
Student stu = new Student("李四",18,"202001","大数据");
try {
//由于major是用private修饰的,所以想要查看值,则需要暴力反射
majorField.setAccessible(true);
Object value = majorField.get(stu);
System.out.println(value);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
//修改成员变量的值
try {
majorField.set(stu,"人工智能");
} catch (IllegalAccessException e) {
e.printStackTrace();
}
System.out.println(stu);
}
}
四、利用反射获取成员方法
Class类中用于获取成员便方法的方法
Method[] getMethods():返回所有公共成员方法对象的数组,包括继承的 Method[] getDeclaredMethods():返回所有成员方法对象数组,不包括继承的 Method getMethod(String name,Class<?>...parameterTypes):返回单个公共成员方法对像。第一个参数是方法的名字,后面的参数是方法的参数 Method getDeclaredMethod(String name,Class<?>...parameterTypes):返回单个成员方法对象
成员方法也有修饰符和参数等,都和构造方法的获取方式一样
Mehod类中用于创建对象的方法
Object invoke(Object obj,Object...args):运行方法
参数一:用obj对象调用该方法
参数二:调用方法的传递的参数(如果没有就不写)
返回值:方法的返回值(如果没有就不写)
package exam;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class Test1 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException {
//1、获取class字节码文件对象
Class clazz1 = Class.forName("exam.Student");
//获取所有公共方法,包括继承来的
Method[] methods = clazz1.getMethods();
for (Method method : methods) {
System.out.println(method);
}
System.out.println("------------");
//获取所有方法对象,不包括继承的,但包括私有的等
Method[] methods1 = clazz1.getDeclaredMethods();
for (Method method : methods1) {
System.out.println(method);
}
System.out.println("------------");
//获取单个方法
Method method = null;
try {
method = clazz1.getMethod("eat",String.class);
System.out.println(method);
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
//获取方法的抛出的异常
Class[] exceptionTypes = method.getExceptionTypes();
//方法运行
Student stu = new Student("王麻子",21,"202001","大数据");
try {
method.invoke(stu,"橙子");
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}