JAVA反射 3000字 高质量详解,从零梳理,全套知识点,不懂评论必回

反射的意义:

符合开闭原则,在不修改源码,只修改配置文件的前提下,修改程序的功能。

1、反射机制允许程序在执行期借助Reflection API获取任何类的内部信息,并能操作对象的属性以及方法。反射在设计模式和框架底层都会用到。 

2、加载完类以后堆中产生一个Class对象,他包含类的完整结构信息。他就像一面镜子,透过镜子看到类的结构,所以称之为反射。

 底层原理分析图

首先在代码阶段编写代码——编译以后变为字节码文件——类加载器会将所有的类加载到堆里面——类的内部属性都会被视为对象处理——运行阶段实例化对象——因为每个对象知道对应的Class对象,因此可以得到与之关联的Class,并创建对象、操作属性等。

图中右边部分属于应用、左边部分属于JVM内部原理。

 

反射相关主要的类

反射的优点和缺点

 经过传统方式调用和反射调用同一个方法,测试可得 两者耗时差距十分之大 

如何优化反射的效率 

反射调用时有的对象会有类似权限检查的步骤,会影响运行速度,但是可以手动关闭

 优化幅度不高,但有效果。

Class类概况解析

forName(“类名”) 方法用于根据指定的类名获取对应的 Class 对象。该方法会返回一个对应的 Class 对象。

一个类的class对象在堆中只会创建一次,不管new多少次,只会在运行阶段加载一次。他就像一个模板一样,new的对象就照着他来创建,因此只会加载一次。

Class类常用方法举例,全流程

public class car {
    public String brand = "BENZ";
    public int price = 80;
    public String color = "blue";

    @Override
    public String toString() {
        return "car{" +
                "brand='" + brand + '\'' +
                ", price=" + price +
                ", color='" + color + '\'' +
                '}';
    }
}

public class test {
    public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchFieldException {
        String classPath = "java语法学习.反射.car";//此处为car类的路径引用
        //1、用car类的路径引用获取class对象
        //<?>表示不确定的java类型,可以不写
        Class<?> cla = Class.forName(classPath);
        
        //2、输出cla
        System.out.println(cla);//会输出该class类对应类的路径引用,java语法学习.反射.car
        System.out.println(cla.getClass());//输出cla运行类型java.lang.class
        
        //3、得到包名
        System.out.println(cla.getPackage().getName());
        
        //4.得到全类名
        System.out.println(cla.getName());
        
        //5.通过cla创建对象实例
        car car_ = (car)cla.newInstance();//已经过时
        
        //6、通过反射获取属性
        Field color = cla.getField("color");//定义一个field对象来接收【属性的对象】。私有的无法获取
        System.out.println(color.get(car_));//要get(class实例)来获取
        
        //7、通过反射赋值属性
        color.set(car_,"yellow");//(class实例,修改的值)涉及到修改具体值的,都要和实例(此处为car_)有关
        System.out.println(color.get(car_));
        
        //8、得到所有的字段、属性
        Field[] fields =  cla.getFields();
        for(Field f : fields){
            System.out.println(f.getName());//每个属性的名称
        }
    }
}

获取Class类对象

以下三种方法

p.getClass()Student.class都可以获取到Class对象,但是它们在使用上有一些区别:

  • p.getClass()是在运行时获取对象的实例的类信息。这种方式常用于你在编译时无法确定具体的类,只能在运行时通过实例来获取。例如,你可能正在处理一个Student的父类或接口的引用,而实际的对象可能是Student类或其任何子类的实例。

  • Student.class是在编译时就已经确定的,所以我们称之为静态的方式获取Class对象。这种方式常用于你已经明确知道要操作的Class。例如,你需要创建一个新的Student实例,或者需要访问Student类的静态字段和方法。

总的来说,选择哪种方式取决于你在编译时是否能确定具体的类。如果可以,那么使用.class语法会更直接和高效。如果不可以,那么你可能需要在运行时使用.getClass()方法来获取类信息。

 那些类型有class对象

 

 类加载

1、静态加载:编译时加载相关类,如果没有就报错,依赖性强

2、动态加载:运行时加载需要的类,运行时不用该类,即使不存在该类也不报错,降低了依赖

类的加载过程

 通过反射获取类的结构信息

以上内容整理自韩顺平老师的课程!

持续完善中,感谢你的支持!~​​​​​

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值