Java反射详解

手把手教你搭建三端口DC-DC变换器(含Boost+Buck电路实战) 本文详细介绍了如何从零开始搭建三端口DC-DC变换器,涵盖Boost和Buck电路的硬件设计、元器件选型、电路板布局、焊接技巧、控制系统设计与调试等关键步骤。通过实战案例和优化建议,帮助工程师避开常见陷阱,提升系统效率和稳定性,适用于光伏、储能等电力电子应用场景。 阅读详情

反射,是Java中非常重要的一个功能,如果没有反射,可以说很多框架都难以实现。

什么是反射?说白了就是可以通过Java代码获取装载到方法区的类信息的手段。

当装载一个类时,会在方法区产生一个数据结构,该结构中包含着装载的类的相关信息。字节码可以看成是数据流,那么方法区的这种数据结构可以说是字节码数据流的结构化表现。装载的最终产物就是java.lang.Class类的一个对象,它是Java程序与方法区内部数据结构之间的接口。
那么,我们能通过这个接口访问内部数据结构的哪些信息呢?接下来介绍关于反射常用的一些内容。反射的大部分方法大都与安全管理器有关,本文忽略此部分。

假设有以下代码(一个简单的文章管理代码)

package com.ticmy.reflect;
  
/**
 * 文章管理接口
 * @author Administrator
 */
public interface ArticleInterface {
    publicvoid del(longid) throws Exception;
    publicvoid add(String content)throws Exception;
    publicvoid modify(longid, String content) throwsException;
}

一个简单实现

package com.ticmy.reflect;
  
import java.util.Map;
import java.util.Random;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicLong;
  
public class ArticleManage implementsArticleInterface {
    privatefinal Map<Long, String> articles;
    privateboolean needCheck;
    privatefinal AtomicLong idIncr =new AtomicLong(1);
    publicArticleManage(booleanneedCheck) {
        System.out.println("带参数的构造方法");
        this.needCheck = needCheck;
        articles =new ConcurrentHashMap<Long, String>();
    }
  
    publicArticleManage() {
        System.out.println("默认构造方法");
        this.needCheck =true;
        articles =new ConcurrentHashMap<Long, String>();
    }
  
    publicvoid del(longid) throws Exception {
        System.out.println("删除文章");
        articles.remove(id);
    }
  
    publicvoid add(String content)throws Exception {
        if((!isNeedCheck()) || checkContent()) {
            System.out.println("添加文章");
            articles.put(idIncr.getAndIncrement(), content);
        }
    }
  
    publicvoid modify(longid, String content) throwsException {
        if((!isNeedCheck()) || checkContent()) {
            System.out.println("修改文章内容");
            articles.put(id, content);
        }
    }
  
    publicboolean checkContent()throws Exception {
        System.out.println("检查文章内容");
        Random random =new Random();
        intvalue = random.nextInt(100);
        if(value <20) {
            //20%概率失败
            thrownew Exception("文章内容不合法");
        }
        returntrue;
    }
  
    publicboolean isNeedCheck() {
        returnneedCheck;
    }
}

1、生成一个ArticleInterface实现类的一个对象。

package com.ticmy.reflect;
public class Test {
    publicstatic void main(String[] args) throws Exception {
        ArticleInterface inst = (ArticleInterface)Class.forName("com.ticmy.reflect.ArticleManage")
                .newInstance();
        inst.add("this is a short article");
    }
}

我们可能有以上代码来生成一个ArticleManage的实例。如果以前没接触过反射,肯定会纳闷,这里完全可以用ArticleInterface inst = new ArticleManage();这句来取代反射,用反射来创建对象的意义何在。如果在写这段代码的时候,已经知道要new ArticleManage了,可能确实意义不大。但假如在写代码的时候还不知道com.ticmy.reflect.ArticleManage的存在呢或者压根就是留给二次开发的人去做的呢?可能需要一个配置,里面配置着ArticleInterface实现类的全限定名,而此时在不知道其实现类的情况下,可以用上述方式来创建类的对象了。就好像写spring的那些人,他们根本不知道你要注入的对象类型,无论如何他们也无法在代码中使用new的,反射就能很好的解决这个问题。
上面的代码运行后会发现,newInstance调用后使用的是ArticleManage的默认构造方法,那么该如何使用带boolean参数的构造方法呢?这就是下面要说的内容。

2、获取类的构造方法。
Class类中有几个方法可以用来获取构造方法,getConstructors()、getConstructor(Class… parameterTypes)以及getDeclaredConstructors()、getDeclaredConstructor(Class… parameterTypes)。其中含有Declared的表示获取所有的构造方法,不管其是private,protected,public还是包内可见的。Class中还有其它带来Declared的方法,其情况跟这里类似。而不带Declared的,表示获取的是声明为public的内容。再看参数情况,不带参数的表示获取所有能获取的构造方法(getConstructors获取所有public的构造方法,getDeclaredConstructors获取所有声明的构造方法),而带参数的表示构造方法的参数类型。我们在例子中声明的都是public构造方法,想要调的是带boolean参数的构造方法,因此我们可以用如下方式实现:

package com.ticmy.reflect;
import java.lang.reflect.Constructor;
public class Test {
    publicstatic void main(String[] args) throws Exception {
        Class<?> clazz = Class.forName("com.ticmy.reflect.ArticleManage");
        Constructor<?> constructor = clazz.getConstructor(boolean.class);
        ArticleInterface inst = (ArticleInterface)constructor.newInstance(false);
        inst.add("this is a short article");
    }
}

Constructor里也有newInstance方法,如果构造方法有参数,就按构造方法声明的顺序将参数传进去;如果没有,则可以不传参数。

3、访问类中的字段
可以通过Class中的getFields()、getField(String name)以及getDeclaredFields()、getDeclaredField(String name)来访问类的字段。方法名中带Declared与不带Declared的含义同构造方法。假如现在想改变private类型的needCheck的值,可以用getDeclaredField(String name)方法先获取字段对象,再修改其值:

package com.ticmy.reflect;
import java.lang.reflect.Field;
public class Test {
    publicstatic void main(String[] args) throws Exception {
        Class<?> clazz = Class.forName("com.ticmy.reflect.ArticleManage");
        ArticleInterface inst = (ArticleInterface)clazz.newInstance();
        Field field = clazz.getDeclaredField("needCheck");
        field.setAccessible(true);
        field.setBoolean(inst,false);
        inst.add("this is a short article");
    }
}

获取到Field对象后,通过调用其setBoolean方法修改其值。其第一个参数为想要改变字段值的对象,若是static字段,该参数可为null;如果字段为其它类型,可以调用Field类的其它setXXX方法来修改。注意到代码中有一句field.setAccessible(true),如果没有这句会报以下错误,不允许修改private变量的值,将其设置为true,就允许改变了:
Exception in thread “main” java.lang.IllegalAccessException: Class com.ticmy.reflect.Test can not access a member of class com.ticmy.reflect.ArticleManage with modifiers “private”

4、访问类中的方法
Class类中提供了getMethods()、getMethod(String name, Class… parameterTypes)以及getDeclaredMethods()、getDeclaredMethod(String name, Class… parameterTypes),其情况类似于构造方法,毋庸多言。需要说的是其带参数的方法,第一个参数是方法名,后面是对应方法的参数类型。假如这里要调用modify方法,可以先通过getMethod(String name, Class… parameterTypes)获得对应的Method对象,然后通过invoke调用:

package com.ticmy.reflect;
import java.lang.reflect.Method;
public class Test {
    publicstatic void main(String[] args) throws Exception {
        Class<?> clazz = Class.forName("com.ticmy.reflect.ArticleManage");
        ArticleInterface inst = (ArticleInterface)clazz.newInstance();
        Method method = clazz.getMethod("modify",long.class, String.class);
        method.invoke(inst,3, "this is a short article");
    }
}

invoke的第一个参数表示调用的是哪个对象的modify方法,后面是ArticleInterface接口中modify方法按声明顺序排列的实际参数。

5、上述内容是关于反射中常用的一些方法和用法,更多功能参见java.lang.Class,java.lang.reflect.Method、java.lang.reflect.Field、java.lang.reflect.Constructor等类的JAVA API说明。

6、反射和动态代理的结合。
动态代理用于创建动态代理类,这些类不需要以java class文件的形式存在。动态代理相关的类为:java.lang.reflect.Proxy。可以通过其newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h)方法创建一个代理类,其中,loader为定义代理类的类加载器,interfaces为生成的代理类要实现的接口列表,h为指派方法调用的调用处理程序。在ArticleManage示例类中,add和modify方法中都有if((!needCheck) || checkContent())的判断,或许还有更多方法需要这种判断,在每个方法里都写这样的判断实在是太麻烦,动态代理+方法反射调用就可以帮我们解脱痛苦:
现在将ArticleManage实现中的if判断删除:

package com.ticmy.reflect;
  
import java.util.Map;
import java.util.Random;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicLong;
  
public class ArticleManage implementsArticleInterface {
    privatefinal Map<Long, String> articles;
    privateboolean needCheck;
    privatefinal AtomicLong idIncr =new AtomicLong(1);
    publicArticleManage(booleanneedCheck) {
        System.out.println("带参数的构造方法");
        this.needCheck = needCheck;
        articles =new ConcurrentHashMap<Long, String>();
    }
  
    publicArticleManage() {
        System.out.println("默认构造方法");
        this.needCheck =true;
        articles =new ConcurrentHashMap<Long, String>();
    }
  
    publicvoid del(longid) throws Exception {
        System.out.println("删除文章");
        articles.remove(id);
    }
  
    publicvoid add(String content)throws Exception {
        System.out.println("添加文章");
        articles.put(idIncr.getAndIncrement(), content);
    }
  
    publicvoid modify(longid, String content) throwsException {
        System.out.println("修改文章内容");
        articles.put(id, content);
    }
  
    publicboolean checkContent()throws Exception {
        System.out.println("检查文章内容");
        Random random =new Random();
        intvalue = random.nextInt(100);
        if(value <20) {
            //20%概率失败
            thrownew Exception("文章内容不合法");
        }
        returntrue;
    }
  
    publicboolean isNeedCheck() {
        returnneedCheck;
    }
}

通过动态代理为其加上判断功能

package com.ticmy.reflect;
  
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
  
public class Test {
    public static void main(String[] args) throws Exception {
        ArticleManage delegationObj = new ArticleManage();
  
        ArticleInterface inst = (ArticleInterface)Proxy.newProxyInstance(
                ArticleInterface.class.getClassLoader(),
                new Class[]{ArticleInterface.class},
                new ArticleManageInvocationHandler(delegationObj));
        inst.add("this is a short article");
  
    }
  
    static class ArticleManageInvocationHandler implements InvocationHandler {
        private ArticleManage delegationObj;
        public ArticleManageInvocationHandler(ArticleManage delegationObj) {
            this.delegationObj = delegationObj;
        }
        public Object invoke(Object proxy, Method method, Object[] args) throws Exception {
            String methodName = method.getName();
            Object ret = null;
            long start = System.currentTimeMillis();
  
            if(methodName.equals("add")) {
                ret = method.invoke(delegationObj, args);
            } else {
                if((!delegationObj.isNeedCheck()) || delegationObj.checkContent()) {
                    ret = method.invoke(delegationObj, args);
                }
            }
            long end = System.currentTimeMillis();
            System.out.println("[方法调用][" + methodName + "]耗时:" + (end - start) + "ms");
            return ret;
        }
    }
}

看这部分

ArticleInterface inst = (ArticleInterface)Proxy.newProxyInstance(
        ArticleInterface.class.getClassLoader(),
        new Class[]{ArticleInterface.class},
        new ArticleManageInvocationHandler(delegationObj));

让生成的代理类实现ArticleInterface接口,这样就可以将newProxyInstance的对象强制转换成ArticleInterface类型了。在InvocationHandler中,可以看到其invoke方法参数中有个Method,这个Method对象是代理接口中的那些方法,例如这里将其强制转换成ArticleInterface后,假设调用了add方法,InvocationHandler中invoke方法的method就相当于ArticleInterface.class.getMethod(“add”, String.class)。在这个例子中,当调用inst的方法时,就会自动去调用ArticleManageInvocationHandler中的invoke方法。invoke方法的第三个参数,就是调用inst中方法时传的参数。invoke方法的第一个参数即为生成的代理类对象本身,很多时候这个参数用处不大。
既然调用inst的方法时会调用这个invoke方法,那就可以在里面做一些事情了。像上面在调用实际方法之前给其加了判断,为整个方法调用计时等等,有没有种面向切面的感觉?

这是很常用的一种编程模式,如在现实中很多操作需要验证用户是否已经登录,那么就可以通过这种方式来做。如果用了spring,可以使用spring的AOP来做,道理是类似的。


基于IC动态加权的机器学习多因子选股策略:从模型融合到实战回测 在量化投资领域,多因子选股模型通过挖掘市场数据中的有效信号来预测股票收益。其核心原理在于利用统计学与机器学习算法,从海量因子中识别出与未来收益具有稳定相关性的特征。这一技术的核心价值在于将主观投资决策转化为系统化、可重复的客观过程,从而在控制风险的前提下追求超额收益。其典型应用场景包括股票阿尔法策略构建、Smart Beta产品设计以及资产配置中的股票筛选环节。本文聚焦于如何通过信息系数(IC)这一关键指标,动态融合Ridge回归、MLP神经网络和随机森林等多个预测模型,构建一个能够自适应市场风格轮动的选股 阅读详情

相关推荐

简易电梯控制系统设计(两层楼)(

(电子科技大学 数字系统实验二 结课验收项目 ) 题目要求:

m0_48801027的博客 1万+

www.gvlib video.php,www.gvlib.com

Domain Name: gvlib.comRegistrar URL: http://www.godaddy.comRegistrant Name: Bin SongRegistrant Organization:Name Server: NS1.51DNS.COMName Server: NS2.51DNS.COMDNSSEC: unsignedFor complete domain deta...

weixin_33238848的博客 7554

VSCode配置ClangFormat:让C++大括号乖乖不换行(附常见样式对比)

本文详细介绍了如何在VSCode中配置ClangFormat,实现C++代码大括号不换行的格式化风格。通过对比Attach、Allman等主流大括号样式,并提供从快速设置到项目级配置的完整指南,帮助开发者打造统一、高效的代码格式化工作流,提升团队协作效率。

weixin_28835551的博客 215

闭包,懂不懂由你,反正我是懂了

越来越觉得国内没有教书育人的氛围,为了弄懂JS的闭包,我使出了我英语四级吃奶的劲去google上搜寻着有关闭包的解释,当我看到stackoverflow上这一篇解答,我脑中就出现了一句话:就是这货没跑了! 不才译文见下,见笑了。 Peter Mortensen问: 就像老Albert所说的,“如果你不能向一个六岁的孩子解释清楚,那么其实你自己根本就没弄懂。”好吧,我试着向一个2...

weixin_30659829的博客 240

手把手教你为高云DDR3控制器添加物理约束:从位置锁定到参数配置

本文详细介绍了在高云FPGA平台上为DDR3控制器添加物理约束的实战指南,从位置锁定到参数配置。通过解析高云DDR3控制器的架构,提供关键模块的位置约束和参数调优方法,帮助开发者解决时序不稳定、初始化失败等常见问题,实现稳定可靠的DDR3接口。

weixin_33738555的博客 272

Git下载安装及环境配置,解决安装包下载慢问题(详细版)

Git是我们平时开发都要用到的项目管理工具,虽然有网页版的Git网站,但是在本地安装Git后,可以直接使用命令语句来进行项目的上传与克隆。还是非常方便的。今天就来介绍下Git的下载。1、首先在浏览器中搜索Git,进入到Git的官方下载界面或者直接复制下面这个链接。 2、点击download进入下载界面,选择自己需要平台的文件 3、下载标准版就可以4、但是会发现下载速度很慢,就找个镜像版 5、点击 https://registry.npmmirror.com/binary.html?path=git-for-

mengxiang_的博客 6万+

java 反射——使用详解

网上对于java反射的解释已经很多了,很多官方的语言我们并不能很好的理解。我在这里说的通俗些,java反射的作用就是让我们从java虚拟机里面生成的class来进行反序列化得到这个类的实例。那么它的用处就更加多了,例如android中startyactivity()方法传入的Intent对象。

boolean的博客 3713

从隐式求解器到显式求解器:COMSOL接触仿真中的求解策略对比与选择

本文深度解析了COMSOL中隐式与显式求解器在接触仿真中的应用与选择策略。针对非线性接触问题的核心挑战,详细对比了两种求解器的数学框架、优化技术及适用场景,并提供了参数调优和调试技巧,帮助工程师高效解决接触仿真中的收敛问题。

weixin_28347369的博客 681

java boolean方法_程序猿都要懂的Java反射机制

问题:在运行时,对一个JAVA类,能否知道属性和方法;能否调用它的任意方法?答案是可以的,JAVA提供一种反射机制可以实现。目录什么是JAVA的反射机制JDK中提供的Reflection APIJAVA反射机制提供了什么功能获取类的Class对象获取类的Fields获取类的Method获取类的Constructor新建类的实例Class的函数newInstance通过Constructor对象的方...

weixin_34363835的博客 835

《民机适航入门指南:从法规学习到项目实践的全面解析》

适航(Airworthiness)是指航空器、其发动机、螺旋桨和其他部件在规定条件下,能够安全飞行并满足有关航空法规规定的条件。简而言之,适航代表了航空器在任何时候都能安全运营的状态。适航在民用航空领域尤为关键,因为飞机必须经过严格的适航认证才能投入商用。这些认证的目标是确保飞机能够在广泛的运行条件下保持飞行安全,从而保护乘客、机组和地面人员的生命财产安全。适航法规覆盖了飞机的整个生命周期,包括设计、制造、测试、运营、维护和报废。

qq_41854911的博客 992

从零打造高速 SerDes 系统:一步步教你生成 IBIS-AMI 模型!(含Simulink实操)

一个完整的 SerDes 系统,不止是电路设计,更是 SI 仿真、IBIS建模、系统验证三位一体的过程。用 MATLAB 的 SerDes Designer + Simulink 组合拳,不仅可以快速完成设计,还能无缝衔接工业标准流程,非常适合个人学习 & 企业验证。如果你还没用过,建议马上动手试一遍,毕竟:“光说不练假把式,跑出眼图才是王道!”🔥。

weixin_43199439的博客 1142

java 反射 参数类型_java – 如何使用反射获取参数类型?

当我必须查找方法时,我通常做的是从我正在进行的查询生成缓存键,并将此缓存键保存在地图中.例:我知道方法参数是Boolean.TRUE,Arrays.asList(“foo”,“bar”,“baz”)和BigInteger.valueOf(77777l)我的类包含一个带签名的方法public foo(boolean, Collection, Number)我无法直接将参数映射到参数类型,因为我只是不...

weixin_30026331的博客 1707

YOLOv13改进策略【Backbone/轻量化】| 替换骨干网络 CVPR-2024 StarNet,超级精简高效的轻量化模块

本文记录的是。StarNet设计简洁,没有复杂的设计和精细调整的超参数,仅是一个 4 阶段的分层架构。并且其中能够在低维空间计算的同时考虑极高维的特征这一特性,进而提高模型精度。本文在替换骨干网络中配置了原论文中的starnet_s1starnet_s2starnet_s3和starnet_s4七种模型,以满足不同的需求。

Limiiiing的博客 669

Java 反射

反射(reflection)是 Java 中的一项特性,它允许程序在运行时查询和操作类的信息。即,在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能调用它的任意方法和属性。获取到方法和属性后,就可以对其进行修改。这种动态获取信息以及动态调用对象方法的功能也就是Java的反射机制

2301_76161469的博客 8772

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

Java 反射详解和使用

反射(Reflection)机制是Java语言特性之一,是Java被视为动态(或准动态)语言的一个关键特性;

m0_58375976的博客 8325

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

java 反射 详解

java 反射 详解

T_Y_F_的博客 1130

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

JAVA【反射】详解

JAVA反射机制是在运行时,对于任意一个类,都能够知道这个类的所有方法和属性;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。

Locus的博客 917

【Java】反射详解

本文详细介绍了Java反射机制,主要包括以下内容:1. 反射概述,解释了反射的概念、应用场景及优缺点;2. 获取Class对象的三种方式及类信息获取方法;3. 构造方法反射操作,包括获取构造方法、创建对象实例等。文章通过代码示例演示了如何使用反射动态获取类信息、操作构造方法,适用于框架开发、动态代理等场景,但需注意反射的性能开销和封装性问题。

小昭的博客 1680

详解Java反射

Java反射机制是静态类型语言的动态特性,允许程序在运行时获取类信息、调用方法和修改属性。摘要如下: 反射基础:Java作为静态语言,类型检查在编译时完成,而反射打破了这一限制,实现动态操作。 获取Class对象的三种方式: 类名.class(编译时已知) 对象.getClass() Class.forName("类名")(最灵活) 核心操作: 实例化对象(包括处理私有构造方法) 动态调用方法 修改属性(包括私有成员) 特殊场景处理: 单例模式实例化(如Runtime类) 内部类反射写法

Python1111111的博客 1153

JAVA反射调用详解

JAVA反射调用的确是一种很神奇的机制,在项目中使用后恋恋不忘,现将其好好整理一下。 参考: 学习JAVA应该如何理解反射?知乎 https://www.zhihu.com/question/24304289 全面细致讲解反射机制系列 http://www.365yg.com/item/6414118008049893889/?iid=9697930986&app=news_artic

Aka丶的博客 8194

java反射&python反射

作为一只主学java,次学python的猿,反射的梗,怎能不知道 一、反射是什么: 维基百科上给出的定义:在计算机科学中,反射是指计算机程序在运行时(Run time)可以访问、检测和修改它本身状态或行为的一种能力。用比喻来说,反射就是程序在运行的时候能够“观察”并且修改自己的行为。 以我浅薄的编程思想理解的反射: 反射可以让我们在不打开程序文件的情况下,清楚的知道该程序的内部结构...

远处 1475

详解 Java 反射

反射,反射,程序员的快乐!

Alpinist Wang 884

【Java反射详解】

所谓的反射就是java语言在运行时拥有的一种自观的能力,反射使您的程序代码能够得到装载到JVM中的类的内部信息,允许您执行程序时才得到需要类的内部信息,而不是在编写代码的时候就必须要知道所需类的内部信息;也可以通俗的将这种动态获取信息以及动态调用对象的方法称为Java的反射机制.通过Java的反射机制,程序猿们可以更深入的控制程序的运行过程,如在程序运行时对用户输入的信息进行验证,还可以逆向控制程序的执行过程,这也使反射成为构建灵活的应用的主要工具。

qq_73918355的博客 1138
上一篇: Java反射机制及应用(一)
下一篇: JSP和Servlet设置编码
SOMECT
博客等级 码龄15年 11粉丝 35原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值