目录
一、反射的概述
1.什么是反射
是指在运行时去获取一个类的变量和方法信息。然后通过获取到的信息来创建对象,调用方法的一种机制。
2.反射的好处
由于反射这种动态性,可以极大的增强程序的灵活性,程序不用在编译期就完成确定,在运行期仍然可以扩展
二、如何获取Class对象
1.三种方式
类名.class属性
对象名.getClass()方法
Class.forName(全类名)方法
2.代码示例
public class ReflectDemo {
public static void main(String[] args) throws ClassNotFoundException {
//使用类的class属性来获取该类对应的Class对象
Class<Student> c1 = Student.class;
System.out.println(c1);
Class<Student> c2 = Student.class;
System.out.println(c1 == c2);
System.out.println("--------");
//调用对象的getClass()方法,返回该对象所属类对应的Class对象
Student s = new Student();
Class<? extends Student> c3 = s.getClass();
System.out.println(c1 == c3);
System.out.println("--------");
//使用Class类中的静态方法forName(String className)
Class<?> c4 = Class.forName("com.itheima_02.Student");
System.out.println(c1 == c4);
}
}
三、反射获取构造方法
1.方法分类
方法名 | 说明 |
---|---|
Constructor<?>[] getConstructors() | 返回所有公共构造方法对象的数组 |
Constructor<?>[] getDeclaredConstructors() | 返回所有构造方法对象的数组 |
Constructor<T> getConstructor(Class<?>... parameterTypes) | 返回单个公共构造方法对象 |
Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes) | 返回单个构造方法对象 |
2.Constructor类中创建对象的方法
方法名 | 说明 |
---|---|
T newInstance(Object...initargs) | 根据指定的构造方法创建对象 |
3.代码示例
public class ReflectDemo01 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
//获取Class对象
Class<?> c = Class.forName("com.itheima_02.Student");
//Constructor<?>[] getConstructors() 返回一个包含 Constructor对象的数组, Constructor对象反映了由该 Class对象表示的类的所有公共构造函数
// Constructor<?>[] cons = c.getConstructors();
//Constructor<?>[] getDeclaredConstructors() 返回反映由该 Class对象表示的类声明的所有构造函数的 Constructor对象的数组
Constructor<?>[] cons = c.getDeclaredConstructors();
for(Constructor con : cons) {
System.out.println(con);
}
System.out.println("--------");
//Constructor<T> getConstructor(Class<?>... parameterTypes) 返回一个 Constructor对象,该对象反映由该 Class对象表示的类的指定公共构造函数
//Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes) 返回一个 Constructor对象,该对象反映由此 Class对象表示的类或接口的指定构造函数
//参数:你要获取的构造方法的参数的个数和数据类型对应的字节码文件对象
Constructor<?> con = c.getConstructor();
//Constructor提供了一个类的单个构造函数的信息和访问权限
//T newInstance(Object... initargs) 使用由此 Constructor对象表示的构造函数,使用指定的初始化参数来创建和初始化构造函数的声明类的新实例
Object obj = con.newInstance();
System.out.println(obj);
// Student s = new Student();
// System.out.println(s);
}
}
四、反射获取成员变量
1.方法分类
方法名 | 说明 |
---|---|
Field[] getFields() | 返回所有公共成员变量对象的数组 |
Field[] getDeclaredFields() | 返回所有成员变量对象的数组 |
Field getField(String name) | 返回单个公共成员变量对象 |
Field getDeclaredField(String name) | 返回单个成员变量对象 |
2.Field类中成员变量赋值的方法
方法名 | 说明 |
---|---|
voidset(Object obj,Object value) | 给obj对象的成员变量赋值为value |
3.代码示例
public class ReflectDemo01 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
//获取Class对象
Class<?> c = Class.forName("com.itheima_02.Student");
//Field[] getFields() 返回一个包含 Field对象的数组, Field对象反映由该 Class对象表示的类或接口的所有可访问的公共字段
//Field[] getDeclaredFields() 返回一个 Field对象的数组,反映了由该 Class对象表示的类或接口声明的所有字段
// Field[] fields = c.getFields();
Field[] fields = c.getDeclaredFields();
for(Field field : fields) {
System.out.println(field);
}
System.out.println("--------");
//Field getField(String name) 返回一个 Field对象,该对象反映由该 Class对象表示的类或接口的指定公共成员字段
//Field getDeclaredField(String name) 返回一个 Field对象,该对象反映由该 Class对象表示的类或接口的指定声明字段
Field addressField = c.getField("address");
//获取无参构造方法创建对象
Constructor<?> con = c.getConstructor();
Object obj = con.newInstance();
// obj.addressField = "西安";
//Field提供有关类或接口的单个字段的信息和动态访问
//void set(Object obj, Object value) 将指定的对象参数中由此 Field对象表示的字段设置为指定的新值
addressField.set(obj,"西安"); //给obj的成员变量addressField赋值为西安
System.out.println(obj);
// Student s = new Student();
// s.address = "西安";
// System.out.println(s);
}
}
五、反射获取成员方法
1.方法分类
方法名 | 说明 |
---|---|
Method[] getMethods() | 返回所有公共成员方法对象的数组,包括继承的 |
Method[] getDeclaredMethods() | 返回所有成员方法对象的数组,不包括继承的 |
Method getMethod(String name, Class<?>... parameterTypes) | 返回单个公共成员方法对象 |
Method getDeclaredMethod(String name, Class<?>... parameterTypes) | 返回单个成员方法对象 |
2.Method类中执行方法的方法
方法名 | 说明 |
---|---|
Objectinvoke(Object obj,Object... args) | 调用obj对象的成员方法,参数是args,返回值是Object类型 |
3.代码示例
public class ReflectDemo02 { public static void main(String[] args) throws Exception { //获取Class对象 Class<?> c = Class.forName("com.itheima_02.Student"); //Student s = new Student(); Constructor<?> con = c.getConstructor(); Object obj = con.newInstance(); //s.method1(); Method m1 = c.getMethod("method1"); m1.invoke(obj); //s.method2("林青霞"); Method m2 = c.getMethod("method2", String.class); m2.invoke(obj,"林青霞"); // String ss = s.method3("林青霞",30); // System.out.println(ss); Method m3 = c.getMethod("method3", String.class, int.class); Object o = m3.invoke(obj, "林青霞", 30); System.out.println(o); //s.function(); // Method m4 = c.getMethod("function"); //NoSuchMethodException: com.itheima_02.Student.function() Method m4 = c.getDeclaredMethod("function"); m4.setAccessible(true); m4.invoke(obj); } }
六、暴力反射
1.概述
反射中强制使用得到的私有成员(构造方法、成员变量、成员方法)
2.暴力反射解决的问题
虽然Class类中有方法可以得到私有的构造方法,但使用该私有构造方法创建对象会抛出异 常(IllegalAccessException)(异常访问异常)。因为按照常理私有构造方法是无法创建对象的。
3.暴力反射的使用
反射中各成员(构造方法、成员变量、成员方法)所属类都有setAccessible(boolean flag)方法值为true时,取消访问检查。
如何使用
反射中执行私有成员(构造方法、成员变量、成员方法)前,使用setAccessible(boolean flag)方法声明取消检查即可
七、创作不易恳求一键三连啦!!