Java反射机制分析

1、反射机制的概念

指在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法,对于任意一个对象,都能操作它的任意一个方法和属性。这种动态获取信息,以及动态调用对象方法的功能叫Java语言的反射机制。

本质是JVM得到class对象之后,再通过class对象进行反编译,从而获取对象的各种信息。

2、反射的原理

为了彻底理解反射的原理,可以先理解一下虚拟机的工作机制。

通常,java在编译之后,会将Java代码生成为class源文件,JVM启动时,将会载入所有的源文件,并将类型信息存放到方法区中;将所有对象实例存放在Java堆中,同时也会保存指向类型信息的引用。

反射首先需要获取到这个对象存放在方法区的类型信息,获取到类型信息后,我们就知道这个类的构造器、属性、方法、注解、子类、父类等等信息了,这个时候,我们就可以通过这些类型信息来回调处理对象,来完成自己想要的操作了。

3、反射的优缺点

(1)优点:在运行时获得类的各种内容,进行反编译,对于Java这种先编译再运行的语言,能够让我们很方便的创建灵活的代码,这些代码可以在运行时装配,无需在组件之间进行源代码的链接,更加容易实现面向对象。

(2)缺点:

  • 反射会消耗一定的系统资源,因此,如果不需要动态地创建一个对象,那么就不需要用反射;
  • 反射调用方法时可以忽略权限检查,因此可能会破坏封装性而导致安全问题。

4、反射的用途

反射功能通常用于检查或修改Java虚拟机运行中(runtime)的应用程序的行为,这一句话就精准的描述了反射的全部功能,更详细来说可以分为以下几点:

        1. 在运行中分析类的能力,可以通过完全限定类名创建类的对象实例。

        2. 在运行中查看和操作对象,可以遍历类的成员变量。

        3. 反射允许代码执行非反射代码中非法的操作,可以检索和访问类的私有成员变量,包括私有属性、方法等。

注意:要有选择的使用反射功能,如果可以直接执行操作,那么最好不要使用反射。

 5、在Java中应用反射

1. 获取Class对象

 (1)知道具体类的情况下可以使用

Class<String> aClass0 = String.class;

(2)通过 Class.forName()传入类的全路径获取

Class aClass1 = Class.forName("cn.dailyTest.TargetObject");

(3)通过对象实例instance.getClass()获取

TargetObject o = new TargetObject();
Class<? extends TargetObject> aClass1 = o.getClass();

(4)通过类加载器xxxClassLoader.loadClass()传入类路径获取

Class clazz = ClassLoader.loadClass("cn.dailyTest.TargetObject");

通过类加载器获取 Class 对象不会进行初始化,意味着不进行包括初始化等一系列步骤,静态代码块和静态对象不会得到执行

2. 通过反射机制去获取类的信息

首先创建一个类

public class TargetObject {
    private String value;
    public String name;

    public TargetObject() {
        value = "java";
    }

    public void publicMethod(String s) {
        System.out.println("I love " + s);
    }

    private void privateMethod() {
        System.out.println("value is " + value);
    }
}

 使用反射操作这个类的方法以及参数

public class 反射 {
    public static void main(String[] args) throws Exception {

        // 获取 TargetObject 类的 Class 对象并且创建 TargetObject 类实例
        Class<?> targetClass = Class.forName("com.dailyTest.TargetObject");
        System.out.println(targetClass);
        TargetObject targetObject = (TargetObject) targetClass.newInstance();

        // 获取 TargetObject 类中定义的所有方法
        Method[] methods = targetClass.getDeclaredMethods();
        for (Method method : methods) {
            System.out.println(method.getName());
        }

        // 获取指定方法并调用
        Method publicMethod = targetClass.getDeclaredMethod("publicMethod", String.class);
        publicMethod.invoke(targetObject, "反射");

        // 获取指定参数并对参数进行修改
        Field field = targetClass.getDeclaredField("value");

        // 为了对类中的参数进行修改我们取消安全检查
        field.setAccessible(true);
        field.set(targetObject, "fanShe!");

        // 调用 private 方法
        Method privateMethod = targetClass.getDeclaredMethod("privateMethod");

        // 为了调用private方法我们取消安全检查
        privateMethod.setAccessible(true);
        privateMethod.invoke(targetObject);
    }
}

输出:

class com.dailyTest.TargetObject
privateMethod
publicMethod
I love 反射
value is fanShe!

3. 反射可获取类的所有信息

包括:modifier、constructor、field、method

4. 反射方法的其他使用--通过反射越过泛型检查

泛型用在编译期,编译过后泛型擦除(消失掉),所以是可以通过反射越过泛型检查的。


public static void main(String[] args) throws Exception {
    ArrayList<String> stringList = new ArrayList<>();
    stringList.add("aaa");
    stringList.add("bbb");
//        stringList.add(100); // 这里报错,需要的类型是String,提供的类型是int
    // 但是使用反射机制就能把100添加进去
    Class<?> listClass = stringList.getClass();
    Method add = listClass.getMethod("add", Object.class);
    add.invoke(stringList, 100);

    System.out.println(stringList);
    for(Object o : stringList) {
        System.out.println(o.getClass());
    }
}

输出:

[aaa, bbb, 100]
class java.lang.String
class java.lang.String
class java.lang.Integer

思考:泛型是会擦除的,那为什么反射能够获取到泛型的信息呢?

分析:泛型的信息只存在编译阶段,在class字节码就看不到泛型的信息了。其实,可以理解为泛型擦除是有范围的,定义在类上的泛型信息是不会被擦除的。Java编译器仍在class文件以 Signature属性的方式保留了泛型信息。Type作为顶级接口,Type下还有几种类型,比如TypeVariable、ParameterizedType、WildCardType、GenericArrayType、以及Class。通过这些接口我们就可以在运行时获取泛型相关的信息。

思考:都说反射会影响性能,有什么方式可以减低它的性能影响吗?

分析:可以使用缓存把反射的元数据存储起来,下一次使用的时候就可以直接从内存获取了。尽可能使用高性能的反射框架。

Gemini科研手册指南.内容概要:本文介绍了《Gemini科研手册指南》,通过系统化的提示词设计与智能体协同工作流,帮助科研人员高效完成从选题生成、文献检索、精读分析、综述撰写到科研绘图、数据可视化及汇报PPT制作的全流程。手册特别强调Gemini在“研究方案先行”“方案可修订”“面向研究目标的结构化输出”等方面的优势,支持基于真实科研逻辑开展可追溯、可复用、可迭代的研究工作。其核心功能覆盖学术热点与产业趋势交叉分析、高可信文献检索、多篇论文横向对比、机制图与数据图智能生成,并深度融合多模态理解与代码执行能力,实现“描述即生成”的科研辅助体验。; 适合人群:科研新手、硕士/博士研究生、青年科研工作者及需快速切入前沿领域的跨学科研究者;尤其适用于希望提升科研效率、规范研究流程、增强成果可视化表达能力的研究人员。; 使用场景及目标:①快速锁定兼具学术新颖性与产业牵引力的研究方向;②系统性开展文献综述,避免泛化罗列,支持研究路径迭代;③精准生成符合期刊要求的机制图、数据图与技术路线图;④构建从数据到图表再到汇报材料的一体化输出流程;⑤提升科研写作的逻辑性、结构化与学术规范性。; 其他说明:该手册提供大量可直接复用的提示词公式与操作示例,支持与Canvas、Nano Banana等智能体协同,实现从文本指令到高质量科研产出的闭环;建议用户结合自身研究主题灵活调整提示词结构,并充分利用100万token上下文窗口处理大批量文献与复杂任务。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值