Java反射机制
java反射机制是各种框架的基础,因为有了反射,可以实现类的动态加载,只有类在运行期间用到时才加载到内存中,实现动态编程。对于反射机制的理解,主要需要理解类加载的过程,这是非常重要的一点,通过java视频教程整理文档如下:
java程序在计算机存在三个阶段:
代码阶段/编译阶段:.java文件 —编译—> .class文件
**Class类阶段(加载阶段):**通过类加载器(ClassLoader),将.class文件加载到内存在堆内存生成一个Class类对象,包含了对象的所有信息(属性、方法、构造方法、异常、注解、继承、实现等)
**Runtime运行阶段:**根据Class类的信息在运行阶段可以创建对象等。[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CWLTVzHE-1629439356199)(E:\工作相关\00 创新改善\01 知识学习\03 Java学习\反射机制原理图.png)]
类加载过程:
加载过程:将类的class文件读入内存并为之创建一个Class对象。此过程由加载器完成。
链接过程:将类的二进制数据合并到JRE中。
验证:目的是确保Class文件的字节流包含的信息符合当前虚拟机的要求,并且不会危害虚拟机自身安全。包括文件格式验证、元数据验证、字节码引用验证。(可通过关闭大部分类验证缩短类加载时间);
准备:JVM会在该阶段对静态变量分配内存并初始化(对应数据类型默认值),静态变量的内存在方法区进行分配;
解析:JVM将常量池内的符号引用替换为直接引用的过程。
初始化过程:JVM负责对类进行初始化,主要是静态成员。此阶段是执行<clinit()方法的过程,<clinit()方法是由编译器按语句在源文件中的顺序,依次自动收集类中所有静态变量的赋值动作和静态代码块中的语句进行合并。JVM保证同一个类的<clinit()方法在多线程正常加锁、同步。
几种获取Class类对象的方式
1、Class.forName(String className); 类可以不存在编译阶段也不会报错,动态加载。
public class ClassLoadDemo {
public static void main(String[] args) throws ClassNotFoundException {
//编译不会出错,但是运行时类不存在则会抛异常java.lang.ClassNotFoundException
Class<?> aClass = Class.forName("com.java.practice.reflection.Teacher");
}
}
通过对第三行打断点debug查看程序运行过程,可以看到运行到加载类:
public Class<?> loadClass(String name) throws ClassNotFoundException {
return loadClass(name, false); //name:"com.java.practice.reflection.Teacher"
}
2、类.class ; 类必须存在,不然编译报错
public class ClassLoadDemo {
public static void main(String[] args) throws ClassNotFoundException {
// Class<?> aClass = Class.forName("com.java.practice.reflection.Teacher");
//未创建Teacher类时编译报错:Cannot resolve symbol 'Teacher'
Class<Teacher> teacherClass = Teacher.class;
}
通过对第三行打断点debug查看程序运行过程,可以看到运行到加载类:
public Class<?> loadClass(String name) throws ClassNotFoundException {
return loadClass(name, false); //name:"com.java.practice.reflection.Teacher"
}
3、对象.getclass(); 创建了对象,类已经加载到内存,通过getclass()方法会累该类的Class类对象。既然要先创建对象,那类必须存在。
public class ClassLoadDemo {
public static void main(String[] args) throws ClassNotFoundException {
// Class<?> aClass = Class.forName("com.java.practice.reflection.Teacher");
// Class<Teacher> teacherClass = Teacher.class;
//未创建Teacher类时编译报错:Cannot resolve symbol 'Teacher'
Teacher teacher = new Teacher();
Class<? extends Teacher> aClass = teacher.getClass();
}
}
在new Teacher()创建对象时就会进行类的加载
public Class<?> loadClass(String name) throws ClassNotFoundException {
return loadClass(name, false); //name:"com.java.practice.reflection.Teacher"
}
4、通过类加载器ClassLoader得到Class对象
public class ClassLoadDemo {
public static void main(String[] args) throws ClassNotFoundException {
// Class<?> aClass = Class.forName("com.java.practice.reflection.Teacher");
// Class<Teacher> teacherClass = Teacher.class;
//Teacher teacher = new Teacher();
//Class<? extends Teacher> aClass = teacher.getClass();
//获取到一个类加载器ClassLoader
ClassLoader classLoader = Student.class.getClassLoader();
//编译不会出错,但是运行时类不存在则会抛异常java.lang.ClassNotFoundException
Class<?> aClass = classLoader.loadClass("com.java.practice.reflection.Teacher");
}
}
加载类:
public Class<?> loadClass(String name) throws ClassNotFoundException {
return loadClass(name, false); //name:"com.java.practice.reflection.Teacher"
}
反射获取类结构(部分常用API)
java.lang.Class
方法 | 描述 |
---|---|
public String getName(); | 获取全类名 |
public String getSimpleName(); | 获取简单类名 |
public Field[] getFields(); | 获取public修饰的属性,包括本类和父类的 |
public Field[] getDeclaredFields(); | 获取本类中所有属性 |
public Method[] getMethods(); | 获取public修饰的方法,包括本类和父类 |
public Method[] getDeclaredMethods(); | 获取本类所有方法 |
public Constructor<?>[] getConstructors(); | 获取本类所有public修饰的构造器 |
public Constructor<?>[] getDeclaredConstructors(); | 获取本类所有构造器 |
public ClassLoader getClassLoader(); | 获取一个类加载器 |
public Package getPackage(); | 一Package形式返回包信息 |
java.lang.reflect.Field
方法 | 描述 |
---|---|
public int getModifiers(); | 以int的方式返回修饰符,public : 1、default : 0、protected : 4、private : 2、static : 8、final : 16 |
public Class<?> getType(); | 以Class形式返回类型 |
public String getName(); | 返回属性名称 |
java.lang.reflect.Method
方法 | 描述 |
---|---|
public Class<?> getReturnType(); | 以Class形式返回返回值类型 |
public String getName(); | 返回方法名 |
public Class<?>[] getParameterTypes(); | 以Class[]形式返回参数类型数组 |
java.lang.reflect.Constructor
方法 | 描述 |
---|---|
public String getName(); | 返回构造器名称 |
public Class<?>[] getParameterTypes(); |
ps:如果对你有帮助,还请点赞支持。