详谈Java编程之委托代理回调、内部类以及匿名内部类回调(闭包回调)

发布时间 - 2026-01-11 01:14:51    点击率:

最近一直在看Java的相关东西,因为我们在iOS开发是,无论是Objective-C还是Swift中,经常会用到委托代理回调,以及Block回调或者说是闭包回调。接下来我们就来看看Java语言中是如何实现委托代理回调以及闭包回调的。当然这两个技术点虽然实现起来并不困难,但是,这回调在封装一些公用组件时还是特别有用的。所以今天,还是有必要把Java中的委托代理回调以及闭包回调来单独的拿出来聊一下。

本篇博客我们依然依托于实例,先聊聊委托代理回调的实现和使用场景,然后再聊一下使用匿名内部类来进行回调,其实就是我们常说的“闭包”回调。闭包回调的实现方式其实就是匿名内部类的使用。既然本篇博客我们使用到了匿名内部类,我们就再聊一下Java中的内部类的相关东西。

一、委托代理回调

在iOS开发中,我们经常使用到委托代理回调,想TableView、CollectionView等等,这些高级控件会依赖于委托回调来完成一些配置。当然在Java中委托代理回调也是非常有用的,接下来我们就来看一下Java中的委托代理回调。当然在Swift或者OC中的委托代理回调是依托于“协议”的,Swift或者OC中的“协议”其实就是Java语言中的“接口”。所以在Java中的委托代理回调,依然要依托于“接口”来实现。

1、类图

首先我们给出该部分实例的类图,然后我们根据下方的类图来设计实现我们的具体代码。下方就是本部分所设计Demo的类图,当然,从类图中我们也能直观的看到,该示例是比较简单的,一共也就是一个接口两个类。CustomDelegate这个接口是代理类要实现的接口,其中包含了代理类要实现的方法。

从下方的类图中我们可以看出,代理类FirstClass实现了CustomDelegate代理接口,并实现了相关的代理方法。而SecondClass依赖于CustomDelegate接口,也就是说只要是实现了CustomDelegate接口的类都可以作为SecondClass的代理。而FirstClass中含有SecondClass类型的属性,并且FirstClass又实现了CustomDelegate接口,在FirstClass中,我们将secondClass对象的代理类指定为FirstClass,稍后我们在具体实现时将会介绍到。

  

2、代码的具体实现

根据上述类图,我们很容易的就可以给出相应的代码实现。接下来我们就根据上述类图来给出具体的代码实现。

(1)、CustomDelegate的代码实现

下方代码段就是CustomDelegate的具体实现。当然该接口的实现比较简单,就一个setValue(String value)方法。该方法的具体作用是用来相应参数回调的。下方我们会用到该方法。

package com.zeluli.callback.delegate;

public interface CustomDelegate {
  public void setValue(String value);
}

(2)、SecondClass的代码实现

CustomDelegate实现完毕后,接下来我们就来实现一下SecondClass的具体代码。下方代码段就是SecondClass的具体代码实现了。我们从具体实现中可以明确看出,SecondClass类中有个私有的delegate属性,该属性是CustomDelegate类型的,所以SecondClass依赖于CustomDelegate类型。

在SecondClass的构造方法中,我们为delegate指定了具体的对象,然后调用了begin()方法。begin()方法中做的事情也是比较简单的,就是使用了Java中自带的定时器,然后在特定时间的间隔中执行delegate对象的setValue()方法,并且将当前的时间传给setValue()方法。

package com.zeluli.callback.delegate;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;

public class SecondClass {
  private CustomDelegate delegate;

  public SecondClass(CustomDelegate delegate) {
    this.delegate = delegate;
    this.begin();
  }
  
  public void begin() {
    TimerTask task = new TimerTask() {
      @Override
      public void run() {
        delegate.setValue(getNowDate());  //执行委托代理回调方法
      }
    };
    
    long delay = 0; 
    Timer timer = new Timer(); 
    timer.scheduleAtFixedRate(task, delay, 1000); 
  }
  
  private String getNowDate() {
    Date currentTime = new Date();
    SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    String dateString = formatter.format(currentTime);
    return dateString;
  }
}

(3)、FirstClass的创建

接下来我们来创建委托代理类,也就是我们的FirstClass类。其中的代码也是比较简单的,FirstClass类实现了CustomDelegate的相关方法,然后为secondClass对象指定了代理对象就是当前类的对象。具体代码如下所示。

package com.zeluli.callback.delegate;

public class FirstClass implements CustomDelegate {
  private SecondClass secondClass;
  
  public void beginRunSecondDelegateMethod() {
    if(this.secondClass == null) {
      this.secondClass = new SecondClass(this);
    }
  }

  //secondClass回调要执行的方法
  @Override
  public void setValue(String value) {
    System.out.println("第二个类回调过来的值:" + value);
  }

}

3、测试用例和运行结果

接下来我们来看一下上述代码的测试用例和运行结果。下方代码段就是我们的测试用例,代码比较简单,就是实例化了一个FirstClass的类对象firstObj,然后调用相应的方法为其中的secondClass指定代理方法即可,具体如下所示。

package com.zeluli.callback.delegate;

public class Main {
  public static void main(String[] args) throws InterruptedException {
    FirstClass firstObj = new FirstClass();
    firstObj.beginRunSecondDelegateMethod();
  }
}

下方就是上述代码的运行结果,我们可以看出定期会执行FirstClass中的setValue()方法。

  

二、闭包回调

上面我们实现了委托代理回调,接下来我们来对上述示例进行改造。将其改成匿名内部类的实现方式,也就是使用闭包的形式来实现回调。我们只需要讲FirstClass进行修改即可。将其委托代理回调修改成闭包回调的形式。下方代码段就是我们修改后的FirstClass类的源代码。

从下方的源代码可以看出,FirstClass并没有实现CustomDelegate接口。在为SecondClass的对象指定委托代理对象时,我们传入的是一个匿名内部类的对象,而这个对象的类型是CustomDelegate。这种用法,也是匿名内部类的使用方式之一。

  

修改后的代码的测试用例以及运行结果与之前第一部分的委托代理回调的方式一致,在此就不做过多赘述了。

三、内部类

既然,上述我们使用到了匿名内部类,那么接下来的这部分我们就来看看内部类的相关内容。内部类,顾名思义,就是定义在接口、类、方法等结构的内部的类。而匿名内部类,就是没有名字的内部类,这一点也是比较好理解的。下方我们分别从迭代器的示例以及工厂模式的示例中来窥探一下内部类的具体使用场景及使用规则。当然这两个示例所针对的内部类的角度不同。

1、迭代器中的内部类

在之前的文章中,我们详细的聊了迭代器模式,当然之前的迭代器我们是使用的Swift3.0来实现的,今天我们就用Java的内部类来实现一个Java中的迭代器。

(1)、迭代器接口

按照之前的介绍迭代器的套路,我们还是先要创建迭代器接口的。下方的Selector就是我们创建的迭代器接口。

end()方法用来判断序列是否到达了结尾处。

current()方法则用来获取当前序列中下标的值。

next()方法则是移动下标到下一个位置。

为了统一迭代器使用规范性,所有的迭代器都要遵循该接口。具体代码如下所示。

  

(2)、创建序列类以及迭代器内部类

下方创建的就是我们的序列类Sequence,该类中的items数组用来存储元素,而next属性指向当前值的下标。在Sequence类中,除了属性、构造器以及方法外,我们还在其中定义了一个内部类SequenceSelector

SequenceSelector类就是Sequence类的迭代器,并且SequenceSelector要实现迭代器接口Selector。下方我们要注意的一点,在内部类SequenceSelector中,可以直接访问外层类Sequence类的成员属性和方法。因为无论是内部类还是Sequence类的成员属性,都在Sequence类的域中。

当然下方的代码的逻辑是比较简单的,主要是对items数组的操作。具体代码如下所示。

  

(3)、上述迭代器的使用

定义完迭代器后,接下来,我们就来看一下迭代器的使用呢。首先我们创建一个序列对象,然后通过for循环往这个序列对象里边添加对象。紧接着我们从这个序列对象中获取其对应的迭代器对象,然后操作迭代器对序列进行遍历。具体操作如下所示。

  

2、工厂模式中的匿名内部类

聊完迭代器的内部类,接下来我们来看一下工厂模式中的匿名内部类。在之前的文章中,我们详细的聊了工厂模式的具体内容。本篇文章我们就来看一下,匿名内部类在工厂模式中的使用。

(1)、类图

Service接口:首先我们来看一下Service接口,该接口是所有具体的实现类要实现的接口。其中定义这具体的方法声明。我们的实现类都要继承自该接口。

ServiceFactory接口:该接口是所有工厂类要实现的接口,因为本部分我们的工厂类是以匿名内部类的形式来体现的,所有该接口就是我们“匿名内部类”的类型。

Implemention1、2类:这两个类就是我们的具体实现类,我们的工厂就负责实例化这两个类。

Factories类:该类就负责调用工厂方法来创建相关实例,并执行实例的相关方法。

(2)、Service和ServiceFactory接口的具体实现

这两个接口的实现代码比较简单,在此就不做过多赘述了,具体代码如下所示:

package com.zeluli.innerclass.factory;

public interface Service {
  void method1();
  void method2();
}

======================================================

package com.zeluli.innerclass.factory;

public interface ServiceFactory {
  Service getService();
}

(3)、Implementation相关类的实现

Implementation1Implementation2的实现差不多,我们就聊一下Implementation1类的具体代码。从下方代码片段中我们可以看出Implementation1类实现了Service接口,并且给出了接口中相关方法的实现。并且在Implementation1类中有一个ServiceFactory类型的静态变量factory。而factory引用的是一个ServiceFactory类型的匿名内部类的对象。该匿名内部类就是一个工程类,其中有一个方法负责创建当前外围类,也就是Implementation1类的对象。具体实现如下所示。

  

(4)、Factory类的实现

接下来我们就来看看Factory类的实现,Factory中就负责从工厂中获取相应的对象,然后执行对象的相关方法,代码比较简单,就不做过多赘述了。

  

(5)、测试用例与运行结果

接下来我们来看一下上述实例的测试用例以及输出结果,如下所示:

  

以上这篇详谈Java编程之委托代理回调、内部类以及匿名内部类回调(闭包回调)就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持。


# java  # 匿名内部类  # 回调  # Java为什么匿名内部类参数引用需要用final进行修饰?  # java中的匿名内部类总结  # java 中匿名内部类的实例详解  # java中匿名内部类详解  # 老生常谈 java匿名内部类  # 简单谈谈java中匿名内部类构造函数  # java匿名内部类实例代码详解  # 迭代  # 委托代理  # 所示  # 就来  # 实现了  # 这两个  # 可以看出  # 来实现  # 就不  # 类中  # 的是  # 看一下  # 都要  # 在此  # 将其  # 给大家  # 聊了  # 图中  # 源代码 


相关栏目: 【 网站优化151355 】 【 网络推广146373 】 【 网络技术251811 】 【 AI营销90571


相关推荐: 购物网站制作费用多少,开办网上购物网站,需要办理哪些手续?  如何用y主机助手快速搭建网站?  如何撰写建站申请书?关键要点有哪些?  如何彻底卸载建站之星软件?  Chrome浏览器标签页分组怎么用_谷歌浏览器整理标签页技巧【效率】  Android中Textview和图片同行显示(文字超出用省略号,图片自动靠右边)  手机网站制作平台,手机靓号代理商怎么制作属于自己的手机靓号网站?  Bootstrap整体框架之JavaScript插件架构  Laravel Facade的原理是什么_深入理解Laravel门面及其工作机制  Laravel怎么写单元测试_PHPUnit在Laravel项目中的基础测试入门  Android滚轮选择时间控件使用详解  php json中文编码为null的解决办法  Laravel如何创建自定义Facades?(详细步骤)  ,怎么在广州志愿者网站注册?  如何在 Python 中将列表项按字母顺序编号(a.、b.、c. …)  如何在HTML表单中获取用户输入并用JavaScript动态控制复利计算循环  如何在建站宝盒中设置产品搜索功能?  高端建站如何打造兼具美学与转化的品牌官网?  Laravel如何记录自定义日志?(Log频道配置)  焦点电影公司作品,电影焦点结局是什么?  家族网站制作贴纸教程视频,用豆子做粘帖画怎么制作?  Laravel怎么进行数据库事务处理_Laravel DB Facade事务操作确保数据一致性  html文件怎么打开证书错误_https协议的html打开提示不安全【指南】  Laravel如何与Inertia.js和Vue/React构建现代单页应用  Laravel如何实现图片防盗链功能_Laravel中间件验证Referer来源请求【方案】  公司网站制作价格怎么算,公司办个官网需要多少钱?  Laravel如何构建RESTful API_Laravel标准化API接口开发指南  Python进程池调度策略_任务分发说明【指导】  晋江文学城电脑版官网 晋江文学城网页版直接进入  成都网站制作公司哪家好,四川省职工服务网是做什么用?  Laravel 419 page expired怎么解决_Laravel CSRF令牌过期处理  Laravel模型事件有哪些_Laravel Model Event生命周期详解  javascript和jQuery中的AJAX技术详解【包含AJAX各种跨域技术】  Laravel如何实现API版本控制_Laravel版本化API设计方案  EditPlus中的正则表达式 实战(4)  百度输入法ai面板怎么关 百度输入法ai面板隐藏技巧  Laravel如何为API编写文档_Laravel API文档生成与维护方法  详解Android图表 MPAndroidChart折线图  C语言设计一个闪闪的圣诞树  如何在沈阳梯子盘古建站优化SEO排名与功能模块?  Claude怎样写约束型提示词_Claude约束提示词写法【教程】  Laravel怎么实现模型属性的自动加密  如何快速配置高效服务器建站软件?  三星网站视频制作教程下载,三星w23网页如何全屏?  韩国服务器如何优化跨境访问实现高效连接?  专业型网站制作公司有哪些,我设计专业的,谁给推荐几个设计师兼职类的网站?  电商网站制作多少钱一个,电子商务公司的网站制作费用计入什么科目?  Java解压缩zip - 解压缩多个文件或文件夹实例  如何确保FTP站点访问权限与数据传输安全?  php嵌入式断网后怎么恢复_php检测网络重连并恢复硬件控制【操作】