理解java反射机制

本文详细介绍了Java反射机制,它是许多框架的基础,允许在运行时加载和操作类。文章详细阐述了类加载的过程,包括加载、链接(验证、准备、解析)、初始化阶段,并列举了四种获取Class对象的方法。此外,还列出了反射常用API,用于获取类结构信息。通过理解这些内容,开发者可以更好地利用反射实现动态编程。
摘要由CSDN通过智能技术生成

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类对象的方式

1Class.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:如果对你有帮助,还请点赞支持。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值