JAVA反射机制
反射的概述
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
反射就是把java类中的各种成分映射成一个个的Java对象
例如:一个类有:成员变量、方法、构造方法、包等等信息,利用反射技术可以对一个类进行解剖,把个个组成部分映射成一个个对象。
反射的用途
当我们在使用IDEA时,当我们输入一个对象或者类,并想调用他的属性和方法是,一按点号,编译器就会自动列出他的属性或者方法,这里就是用到反射。
反射的基本使用:
要使用反射,首先要获取类的Class对象。
获得字节码文件对象:主要有三种方法:
-
对象.getClass()
-
任何数据类型(包括基本的数据类型)都有一个“静态”的class属性 类.class
-
通过class类的静态方法:forName(String className)(最常用)
package myreflectDemo1;
public class MyReflectDemo {
public static void main(String[] args) throws ClassNotFoundException{
//第一种 对象.getClass()
Student student = new Student();
Class class1 = student.getClass();
System.out.println(class1);
//第二种 类名.class
Class<Student> class2 = Student.class;
System.out.println(class2);
//第三种 Class.forName("全类名")
Class class3 = Class.forName("myreflectDemo1.Student");
System.out.println(class3);
//指向同一个地址 都是Student这个类
System.out.println(class1 == class2);
System.out.println(class2 == class3);
}
}
三种方式中,常用第三种,第一种对象都有了还要反射干什么,第二种需要导入类包,依赖太强,不导包就抛编译错误。一般都使用第三种,一个字符串可以传入也可以写在配置文件中等多种方法。
通过反射获取构造方法并使用:
// Class类中用于获取当前类构造方法的方法 // Constructor[] getConstructors 所有公共的构造方法 // Constructor[] getDeclaredConstructors 所有构造方法 // Constructor getConstructor 单个公共的构造方法 (只能是公共的) // Constructor getDeclaredConstructor 单个构造方法
package myreflectDemo2;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
public class MyReflectDemo {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
//访问构造方法 Constructor
Class class1 = Class.forName("myreflectDemo2.Student");
//获取当前类class字节码文件对象
System.out.println("当前类====="+class1);
// Class类中用于获取当前类构造方法的方法
// Constructor[] getConstructors 所有公共的构造方法
// Constructor[] getDeclaredConstructors 所有构造方法
// Constructor getConstructor 单个公共的构造方法 (只能是公共的)
// Constructor getDeclaredConstructor 单个构造方法
//无参和一个参数的构造方法是私有的,两个参数和全参的构造方法是公共的
System.out.println("--------所有公共的构造方法----------");
Constructor[] constructors1 = class1.getConstructors();
for(Constructor con:constructors1){
System.out.println(con);
}
System.out.println("--------所有构造方法----------");
Constructor[] constructors2 = class1.getDeclaredConstructors();
for(Constructor con:constructors2){
System.out.println(con);
}
System.out.println("--------单个公共的构造方法----------");
//空参构造方法是私有的,会报错
// System.out.println(class1.getConstructor());
Constructor constructor3 = class1.getConstructor(String.class, int.class);
System.out.println(constructor3);
System.out.println("--------单个构造方法----------");
Constructor constructor4 = class1.getDeclaredConstructor();
System.out.println(constructor4);
System.out.println("--------获取构造方法的访问修饰符----------");
//访问修饰符为1 公共的
//访问修饰符为2 私有的
int modifiers1 = constructor3.getModifiers();
int modifiers2 = constructor4.getModifiers();
System.out.println("两个参数的构造方法====="+modifiers1);
System.out.println("无参的构造方法====="+modifiers2);
System.out.println("--------获取构造方法的参数的个数----------");
int parameterCount1 = constructor3.getParameterCount();
int parameterCount2 = constructor4.getParameterCount();
System.out.println("两个参数的构造方法的参数个数====="+parameterCount1);
System.out.println("无参的构造方法的参数个数====="+parameterCount2);
System.out.println("--------获取构造方法创建对象----------");
Student student1 = (Student)constructor3.newInstance("张三", 18);
constructor4.setAccessible(true); // 暴力反射 表示临时取消权限校验
Student student2 = (Student)constructor4.newInstance();
System.out.println("两个参数的构造方法=========="+student1);
System.out.println("无参的构造方法=========="+student2);
}
}
通过反射获取成员变量并使用:
//访问成员变量 Field // Field[] getFields() 获取所有公共的成员变量 // Field[] getDeclaredFields() 获取所有公成语变量 // Field getField(String name) 获取单个公共的成员变量 // Field getDeclaredField (String name) 获取单个成员变量
package myreflectDemo3;
import java.lang.reflect.Field;
public class MyReflectDemo {
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException {
//访问成员变量 Field
// Field[] getFields() 获取所有公共的成员变量
// Field[] getDeclaredFields() 获取所有公成语变量
// Field getField(String name) 获取单个公共的成员变量
// Field getDeclaredField (String name) 获取单个成员变量
//获取字节码class文件的对象
Class class1 = Class.forName("myreflectDemo3.Student");
System.out.println("--------所有公共的成员变量----------");
Field[] fields = class1.getFields();
for (Field field:fields){
System.out.println(field);
}
System.out.println("--------所有成员变量----------");
Field[] fieldss = class1.getDeclaredFields();
for (Field field:fieldss){
System.out.println(field);
}
System.out.println("--------单个公共的成员变量----------");
Field field1 = class1.getField("name");
System.out.println(field1);
System.out.println("--------单个成员变量----------");
Field field2 = class1.getDeclaredField("age");
System.out.println(field2);
//获取访问修饰符 getModifiers
//访问修饰符为1 公共的
//访问修饰符为2 私有的
System.out.println("--------成员变量的访问修饰符类别----------");
int modifiers1 = field1.getModifiers();
int modifiers2 = field2.getModifiers();
System.out.println("name访问修饰符======"+modifiers1);
System.out.println("age访问修饰符======"+modifiers2);
System.out.println("--------成员变量的数据类型----------");
Class<?> type1 = field1.getType();
Class<?> type2 = field2.getType();
System.out.println("name的数据类型======"+type1);
System.out.println("age的数据类型======"+type2);
System.out.println("--------获取成员变量的值----------"); //field1 name的值
Student student = new Student("张三",18);
String s = (String) field1.get(student);
System.out.println("name的值==="+s);
//用反射修改对象成员变量的值 field1 name的值 "张三"-->"李四"
System.out.println("--------修改成员变量的值----------");
field1.set(student,"李四");
System.out.println("name的值==="+student.name);
}
}
通过反射获取构成员方法并使用
//访问成员方法 Method // Method[] getMethods() 获取所有公共的成员方法 // Method[] getDeclaredMethods() 获取所有公成语成员方法 // Method getMethod(形参列表) 获取单个公共的成语成员方法 // Method getMethod (形参列表) 获取单个成语成员方法
package myreflectDemo4;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class MyReflectDemo {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {
//访问成员方法 Method
// Method[] getMethods() 获取所有公共的成员方法
// Method[] getDeclaredMethods() 获取所有公成语成员方法
// Method getMethod(形参列表) 获取单个公共的成语成员方法
// Method getMethod (形参列表) 获取单个成语成员方法
Class<?> class1 = Class.forName("myreflectDemo4.Student");
//getMethods() 获取所有公共的成员方法(包含父类的所有公共的成员方法)
System.out.println("--------所有公共的成员方法----------");
Method[] methods = class1.getMethods();
for (Method method : methods) {
System.out.println(method);
}
//getDeclaredMethods() 获取所有成员方法(不能获取父类的,只能获取本类所有的包含私有的成员方法)
System.out.println("--------所有成员方法----------");
Method[] declaredMethods = class1.getDeclaredMethods();
for (Method declaredMethod : declaredMethods) {
System.out.println(declaredMethod);
}
System.out.println("--------单个公共的成员方法----------");
Method sleep = class1.getMethod("sleep");
Method setAge = class1.getMethod("setAge",int.class);
System.out.println("sleep()方法==="+sleep);
System.out.println("setAge()方法==="+setAge);
System.out.println("--------单个成员方法----------");
Method eat = class1.getDeclaredMethod("eat");
System.out.println("eat()方法==="+eat);
//获取方法的访问修饰符 getModifiers
//访问修饰符为1 公共的
//访问修饰符为2 私有的
System.out.println("--------成员方法访问修饰符----------");
int modifiers = sleep.getModifiers();
int modifiers1 = eat.getModifiers();
System.out.println("sleep()方法访问修饰符==="+modifiers);
System.out.println("eat()方法访问修饰符==="+modifiers1);
//获取方法的参数个数 getParameterCount()
System.out.println("--------成员方法参数个数---------");
int parameterCount = setAge.getParameterCount();
System.out.println("setAge()方法参数个数==="+parameterCount);
//获取方法抛出的异常 getExceptionTypes()
System.out.println("--------成员方法抛出的异常---------");
System.out.println("sleep方法抛出的异常");
Class<?>[] exceptionTypes = sleep.getExceptionTypes();
for (Class<?> exceptionType : exceptionTypes) {
System.out.println(exceptionType);
}
System.out.println("--------成员方法的返回值---------");
Student student = new Student();
Method write = class1.getMethod("write", String.class);
//invoke 第一个参数表示方法的调用者 第二个参数表示传的参数 返回值就是成员方法的返回值
String invoke = (String) write.invoke(student, "张三");
System.out.println(invoke);
}
}