当前位置: 首页 > news >正文

java篇26-Java匿名内部类、invoke方法、动态代理

一、匿名内部类
匿名内部类一般作为方法的参数,这个方法的形参为接口,而实参为匿名内部类(可以理解为接口的对象)并且重写了接口中的方法。
书写形式:

new<接口名>(){@Overvide//重写方法}

例如:
定义了一个接口Star:

类型为Star的引用数据类型作为方法show()的参数,在调用方法show()是传递一个匿名的Star对象且重写了其中的dance方法,执行结果就是执行重写的dance()的内容:

说明:上述代码其实是省略了一般的实现接口的类的步骤,因为该类只用到一次。不适用匿名内部类时的书写步骤如下。

publicclassStar{publicvoiddance();}

新建类实现Star接口:

publicclassDancerimplementsStar{@Overridepublicvoiddance(){System.out.println("跳舞");}}

测试:

publicclassMyTest{publicvoidshow(Starstar){star.dance();}publicstaticvoidmain(String[]args){Starstar=newDancer();show(star);}}

说明:这里只说了接口的例子,其他例子参考另一篇博文《java的内部类》。
二、invoke方法
invoke可以理解为对象方法的另一种调用形式。先通过反射机制获取到类的方法并赋给Method对象,再调用Method对象的invoke()方法,invoke()方法的参数指定类的对象名称,实现调用对象的方法的功能。
当调用的方法没有参数时invoke的参数为一个(参数为对象名称),当调用的方法有一个参数时invoke的参数有两个(第一个是对象名称,第二个是方法实行的实参)。
例如:
定义了一个类BigStar:

使用反射机制获取了BigStar的Class对象,并通过getMethod()获取了sing()方法为methodSing,methodSing.invoke()的作用是调用bigStar对象的sing()方法且方法的参数为"好运来":

执行结果如下:

三、动态代理(要先学反射机制不然看不懂)
动态代理的特点是可以无侵入式的给代码增加额外的功能。一般是通过“自定义的代理类”来管理“指定类”(被代理类)的方法的执行,这里的“管理方法的执行”实质是在方法执行前添加一些代码,表现为方法执行的功能增加了。
java.lang.reflect.Proxy类提供了为对象产生代理对象的方法:

补充:
参数一说明:创建的代理类的字节码文件是通过类加载器(ClassLoader)加载到内存中的,书写形式为“创建的代理类名称.class.getClassLoader()”。
参数二说明:写法为"new Class[]{接口1名称.class,接口2名称.class,…}",这样书写之后就可以将所有接口中的方法交给该代理类。
参数三说明:参数三为匿名内部类,形式为:

newInvocationHandler(Objectproxy,Methodmethod,Object[]args)throwsThrowable{//自定义内容}

类InvocationHandler的匿名对象的第一个属性为proxy即为代理对象,第二个属性method为代理要管理的方法,args为传递的要管理的方法调用时传递的参数。当通过代理对象来执行被代理对象的方法时,method就是该方法,args就是该方法的参数。
换一种说法,给“类的方法增加功能”也可以理解为“将一些功能交给代理做,被代理类不管,只做想做的”,就像明星(被代理类)只负责唱歌跳舞,但是场地布置、收费等工作交给工作人员(代理类)来完成。
注意:JDK的动态代理要求目标对象必须实现接口。对于无接口的类,要为其创建动态代理,就要使用CGLIB,CGLIB动态代理可以不用实现接口(有接口也没问题),CGLIB代理的生成原理是生成目标类的子类,而子类是增强过的,这个子类对象就是代理对象,所以使用CGLIB生成动态代理,要求目标类必须能够被继承,而不是final的对象。CGLIB广泛运用于AOP的框架,例如Spring AOP。
很晕吧,那就用示例说明:
定义一个接口Star,接口中有两个方法sing()和dance():

类BigStar实现了该接口并重写了两个类,增加了name字段和set,get,构造器方法:

定义的代理类ProxyUtil,该代理类的静态方法createProxy()方法的参数为BigStar对象,返回值为Star接口对象,其中使用了Proxy.newProxyInstance()方法创建了一个代理对象,原本的返回值类型为Object,强转为Star类型并返回,这样就可以通过Proxy.createProxy()方法为其参数对象(这里为BigStar对象bigStar)创建代理(即返回值Star对象star)。Proxy.newProxyInstance()方法的第一个参数了解书写形式即可,第二个参数为执行被代理的接口的字节码,第三个参数的作用是对被代理的接口的方法增加功能,注意代理类是可以对接口中所有的方法增加功能,当通过代理类对象调用被代理类的方法时,该方法就传给invoke()方法里的method,代理类对象调用被代理类的方法时的参数传给args。会发现这里的invoke()方法有返回值,实际上是method.invoke()的返回值,也就是代理类对象调用被代理类的方法的返回值(后面说明):

测试如下,通过ProxyUtil.createProxy方法创建了被代理类BigStar的对象bigStar的代理对象proxy(类型为Star),当调用proxy.dance()方法时,Proxy.new ProxyInstance()中的new InvoactionHandler(){}创建的匿名类会发挥作用,将要执行被代理对象bigStar的dance()方法,并在执行之前添加一些操作,先通过判断得出执行的是被代理对象bigStar的dance()方法(上面的if-else语句),然后执行“System.out.println(“准备场地,收钱”);”,再真正执行dance()方法(通过method.invoke(bigStar,args)实现),增加了功能。

补充:
1.之前提到Proxy.new ProxyInstance()中的new InvoactionHandler(){}创建的匿名对象中重写的invoke()方法的返回值,这里通过例子展示功能:

将代理类执行的方法proxy.sing()的结果返回值就是被代理类结果的返回值。

结语:我承认我的讲述很绕很难理解,能理解的人可以表扬一下自己的理解能力。

http://www.jsqmd.com/news/563730/

相关文章:

  • 别再让单片机‘死机’!手把手教你用TPV6823设计一个靠谱的硬件看门狗电路
  • GLM-4.1V-9B-Base行业落地:建筑图纸局部区域语义理解与标注建议
  • 告别复制粘贴:用Python自动化提取微信SQLite数据库中特定联系人的聊天记录
  • 四元数微分方程的数值解法对比:欧拉法 vs 龙格库塔法
  • Kandinsky-5.0-I2V-Lite-5s镜像免配置优势:内置VAE/CLIP/Qwen2.5-VL,开箱即用
  • CEF编译太折腾?我整理了从107到113多个版本的已编译支持MP4的CEF库(含32/64位)
  • AI工程师薪资谈判指南:软件测试从业者的行业数据与策略
  • Go的sync.Map实现原理:read-copy-update模式
  • uniapp学习1,hello world 项目,打包到微信小程序,贪吃蛇小游戏
  • 避开Hugging Face跳转坑!手把手教你从GitHub Releases正确下载YOLOv10预训练模型
  • 2026年AI风口!掌握这三项技能,年薪百万不是梦!一个大模型的新方向,彻底爆发了!!
  • 如何用Captum实现多任务学习解释:复杂模型的归因策略终极指南
  • 告别配置迷茫!手把手教你用DaVinci Configurator配置Autosar NvM Block(含三种类型详解)
  • 从零开始:使用VSCode + CMake + Ninja + GCC构建高效MCU开发环境
  • Masa Mods中文汉化包终极指南:3分钟让Minecraft模组界面变中文!
  • Qwen3-14B私有部署作品集:企业知识库问答与内部智能助手实例
  • 告别复制粘贴!用Automa插件5分钟搞定网页数据自动抓取(保姆级图文教程)
  • Conda环境下的InvalidVersionSpecError:解析与修复版本规范错误
  • Qwen3-ASR-0.6B在STM32嵌入式系统中的应用探索
  • 树莓派通过HTTP协议对接OneNET Studio 5.0物联网平台实战指南
  • Z-Image-Turbo-rinaiqiao-huiyewunv 高清壁纸生成特辑:4K 自然风光与城市夜景
  • KCF算法真的过时了吗?对比SORT、DeepSORT看传统滤波跟踪的生存空间
  • 2026年中大力德减速电机应用白皮书电子设备制造领域剖析:中大力德开关电源一级授权代理商、中大力德开关电源一级授权经销商选择指南 - 优质品牌商家
  • 告别‘离线焦虑’:我的ClamAV病毒库本地化更新与自动化巡检脚本分享
  • Keil MDK开发必备:3种fromelf生成bin文件命令详解(附路径变量解析)
  • Qwen3.5-9B实战案例:用128K上下文做法律合同比对与风险提示
  • DedeCMS 模板缓存注入漏洞:从ShowMsg函数到RCE的完整攻击链剖析
  • Face3D.ai Pro零基础入门:5分钟从照片到可旋转3D人脸模型
  • LLM的“记忆”与“参考书”打架了?深入拆解RAG幻觉的微观机制与调优心得
  • 51单片机项目进阶:给你的交通灯系统加上按键调时和夜间模式(附完整代码)