One Day Day 的
文章目录
一、类的加载
- 加载 头次用到该类的时候会先加载到内存,生成一个class文件
- 检验 加载进去之后会检验是否符合语法规范之类的
- 初始化 用该类做事情
二、反射机制
在运行状态下,动态的获得一个类的信息,并且调用实例的属性和方法,我们称为java的反射机制
2.1 获取Class对象的三种方法
//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();
2.2 获得构造方法,属性和方法
2.2.1获得构造方法Constructor
方法 | 说明 |
---|---|
public Constructor<T> getConstructor(Class<?>… parameterTypes) | 获取public修饰的指定参数类型所对应的构造方法 |
public Constructor<T> getDeclaredConstructor(Class<?>… parameterTypes) | 获取指定参数类型所对应的任意构造方法 |
public Constructor<?>[] getConstructors() | 获取所有公共的构造方法 |
public Constructor<?>[] getDeclaredConstructors() | 获取所有构造方法 |
2.2.2 获取属性Field
方法 | 说明 |
---|---|
public Field getField(String name) | 获取public修饰的指定名称变量 |
public Field getDeclaredField(String name) | 获取指定名称的任意变量 |
public Field[] getFields() | 获取所有公共的变量 |
public Field[] getDeclaredFields() | 获取所有变量 |
2.2.3 获取方法Method
方法 | 说明 |
---|---|
public Method getMethod(String name, Class<?>… parameterTypes) | 获取指定名称和参数类型的一个public修饰的方法 |
public Method getDeclaredMethod(String name, Class<?>… parameterTypes) | 获取指定名称和参数类型的一个任意方法 |
public Method[] getMethods() | 获取所有public修饰的方法 |
public Method[] getDeclaredMethods() | 获取所有方法 |
2.3 使用
使用的时候会发现私有的不让用,这时候我们需要使用
setAccessible(boolean flag)
方法暴力访问。flag = true
取消权限检查
2.3.1 构造方法的使用newInstance(Object… initargs)
//先获取构造方法
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;
2.3.2 属性的使用get(Object o)和set(Object o,Object value)
//和上面的很像的
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);
2.3.3 方法的调用invoke(Object obj,Object… args)
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);
三、反射练习
3.1 泛型擦除
编译后的.class文件没有泛型的约束,所以可以利用反射去添加编译阶段不让添加的东西。
3.2 反射配置文件
这好像是一个很有用的知识点,但是目前只能了解
嘿嘿嘿,练习…就是练习…但是我还没有练,练了以后写在评论区吧。想看我写的可以催一下我……