One Day Day 的
在运行状态下,动态的获得一个类的信息,并且调用实例的属性和方法,我们称为java的反射机制
//1.通过Class类的静态方法:forName("全限定路径名")
Class<?> studentClass1 = Class.forName("Student");
//2. 通过类的class静态属性
Class<Student> studentClass2 = Student.class;
//3. 通过实例的getClass()方法
Student student = new Student(1,"idiot");
Class<? extends Student> studentClass3 = student.getClass();
方法 | 说明 |
---|---|
public Constructor | 获取public修饰的指定参数类型所对应的构造方法 |
public Constructor | 获取指定参数类型所对应的任意构造方法 |
public Constructor>[] getConstructors() | 获取所有公共的构造方法 |
public Constructor>[] getDeclaredConstructors() | 获取所有构造方法 |
方法 | 说明 |
---|---|
public Field getField(String name) | 获取public修饰的指定名称变量 |
public Field getDeclaredField(String name) | 获取指定名称的任意变量 |
public Field[] getFields() | 获取所有公共的变量 |
public Field[] getDeclaredFields() | 获取所有变量 |
方法 | 说明 |
---|---|
public Method getMethod(String name, Class>… parameterTypes) | 获取指定名称和参数类型的一个public修饰的方法 |
public Method getDeclaredMethod(String name, Class>… parameterTypes) | 获取指定名称和参数类型的一个任意方法 |
public Method[] getMethods() | 获取所有public修饰的方法 |
public Method[] getDeclaredMethods() | 获取所有方法 |
使用的时候会发现私有的不让用,这时候我们需要使用
setAccessible(boolean flag)
方法暴力访问。flag = true
取消权限检查
//先获取构造方法
Constructor<?> constructor = studentClass1.getConstructor(int.class, String.class);
//利用constructor中的newInstance(Object... initargs)方法创建实例,注意到返回值是Object类
Object idiot = constructor.newInstance(1, "idiot");
//因此我们进行强转
Student s = (Student) idiot;
接下来要展示暴力访问
Constructor<?> constructor = studentClass1.getDeclaredConstructor();
Object idiot = constructor.newInstance();
Student s = (Student) idiot;
给出以下报错信息,原因是无参构造是私有构造方法
Exception in thread “main” java.lang.IllegalAccessException: class Demo cannot access a member of class Student with modifiers “private”
at java.base/jdk.internal.reflect.Reflection.newIllegalAccessException(Reflection.java:355)
at java.base/java.lang.reflect.AccessibleObject.checkAccess(AccessibleObject.java:639)
at java.base/java.lang.reflect.Constructor.newInstanceWithCaller(Constructor.java:490)
at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:481)
at Demo.main(Demo.java:19)
这时候我们需要使用
setAccessible(boolean flag)
方法暴力访问。flag = true
取消权限检查
Constructor<?> constructor = studentClass1.getDeclaredConstructor();
//看到了没,就是它取消了权限检查
constructor.setAccessible(true);
Object idiot = constructor.newInstance();
Student s = (Student) idiot;
//和上面的很像的
Field name = studentClass1.getField("name");
//这个name是一个Field对象
System.out.println(name);
通过get(Object o)方法获得值,set(Object o,Object value)方法设置值
Field name = studentClass1.getField("name");
System.out.println(name);
//得到null是正常的,这个s是无参构造出来的,用上面的student就没问题了
System.out.println(name.get(s));
name.set(s,"愚者");
//可以看到我们直接修改了值
System.out.println(s.name);
//获得私有属性,就取消下权限,和获取时的方法有差别,剩下的完全一样。
Field id = studentClass1.getDeclaredField("id");
id.setAccessible(true);
Method method = studentClass1.getMethod("ggM", String.class);
//s是实例对象,上面set和get哪个也是要给一个实例对象
Object fanHuiZhi = method.invoke(s, "我是方法的参数");
//确定返回值类型的情况下可以强转的
System.out.println(fanHuiZhi);
Method method = studentClass1.getDeclaredMethod("syM", String.class);
method.setAccessible(true);
Object fanHuiZhi = method.invoke(s, "我是方法的参数");
//确定返回值类型的情况下可以强转的
System.out.println(fanHuiZhi);
编译后的.class文件没有泛型的约束,所以可以利用反射去添加编译阶段不让添加的东西。
这好像是一个很有用的知识点,但是目前只能了解
嘿嘿嘿,练习…就是练习…但是我还没有练,练了以后写在评论区吧。想看我写的可以催一下我……