在 Java 支持方法指针之前,Java 接口不能提供一种实现回调的好方法。如果您习惯于传递在事件驱动编程模型中调用的函数指针,则您会喜欢本技巧。 
熟悉 MS-Windows 和 X Window System 事件驱动编程模型的开发人员,习惯于传递在某种事件发生时调用(即“回调”)的函数指针。Java 的面向对象模型目前并不支持方法指针,这样似乎就不可能使用这种很好的机制。但我们并不是一点办法都没有!

Java 的接口支持提供了一种获得回调的等价功能的机制。其技巧就是:定义一个简单接口,并在该接口中声明我们要调用的方法。

例如,假定我们希望在某个事件发生时得到通知。我们可以定义一个接口: 

public interface InterestingEvent{
// 这仅是一个常规方法。因此如果需要,
// 它可有返回值,也可接收参数。
public void interestingEvent ();
}

这使得我们可以控制实现该接口的类的任何对象。因此,我们不必关心任何外部类型信息。与在将 C++ 代码用于 Motif 时使用窗口小部件的数据域来容纳对象指针的难以控制的 C 函数相比,这种方法要好得多。

发出事件信号的类必须等待实现了 InterestingEvent 接口的对象,并在适当时候调用 interestingEvent() 方法。 

public class EventNotifier{
private InterestingEvent ie;
private boolean somethingHappened; public EventNotifier (InterestingEvent event){
// 保存事件对象以备后用。
ie = event; // 还没有要报告的事件。
somethingHappened = false;
} //... public void doWork (){
// 检查在别处设置的谓词。
if (somethingHappened){
// 通过调用接口的这个方法发出事件信号。
ie.interestingEvent ();
}
//...
} // ...
}

在上例中,我使用 somethingHappened 谓词来跟踪是否应触发事件。在许多情况下,调用此方法足以保证向 interestingEvent() 发出信号。

希望接收事件通知的代码必须实现 InterestingEvent 接口,并将自身引用传递给事件通知程序。 

public class CallMe implements InterestingEvent{
private EventNotifier en; public CallMe (){
// 创建事件通知程序,并将自身引用传递给它。
en = new EventNotifier (this);
} // 为事件定义实际的处理程序。
public void interestingEvent (){
// 噢!必定发生了感兴趣的事件!
// 执行某些操作 ...
} //...
}


下面给出上述例子的完整实现:

/* * 考虑这样一个应用:希望在某个事件发生时得到通知 */
interface InterestingEvent {  public void interestingEvent();  }  class EventNotifier {  private InterestingEvent ie;        //写成private List<InterestingEvent> eventList可以监听多个事件  private boolean somethingHappened;  public EventNotifier(InterestingEvent ie) {  this.ie = ie;  this.somethingHappened = false;  }  public void setHappened() {  this.somethingHappened = true;  }  public void doWork() {  if (somethingHappened) {  ie.interestingEvent();  }  }  }  class ButtonPressedEvent implements InterestingEvent {  @SuppressWarnings("unused")  private EventNotifier en;  public ButtonPressedEvent() {  en = new EventNotifier(this);  }  public void interestingEvent() {  System.out.println("button pressed ");  }  }  class EventNotifierTest {  public static void test() {  //这里有两种调用方法。其中第二种采用匿名内部类,其原理跟上面“改变Client名字”是一样的  EventNotifier en = new EventNotifier(new ButtonPressedEvent());  en.setHappened();  en.doWork();  EventNotifier en2 = new EventNotifier(new InterestingEvent(){  public void interestingEvent() {  System.out.println("inputtext change ");  }  });  en2.setHappened();  en2.doWork();  }
}  //这个类是用来测试的
public class JavaInterfaceCallBack {  public static void main(String[] args) {  ChangeNameTest.test();  EventNotifierTest.test();  }  }  

下面给出回调的模型和另一个实例以便我们更好的学习

/* * Java里面的接口回调,最简单的情况示意如下 */
interface A {}  class B implements A {}  class C implements A {}  class Test {  A b = new B();  A c = new C();
}  
/* * 考虑这样一个应用: NameChanger动态地改变Client的名字 * 那NameChanger的changeName方法就要接收一个Client对象,然后获取(调用)Client的名字并作不同的处理 * Client也要持有NameChanger,因为要打印改变后的名字 */
class Client {  private INameChanger changer;  private String clientName;  public Client(INameChanger changer) {  this.changer = changer;  }  public void showMyNewName() {  String newName = changer.changeName(Client.this);  System.out.println(newName);  }  public String getName() {  return clientName;  }  public void setName(String clientName) {  this.clientName = clientName;  }
}  interface INameChanger {  public String changeName(Client client);  }  public class ChangeNameTest {  public static void main(String[] args) {  Client client = new Client(new INameChanger(){  public String changeName(Client client) {  return "Mr." + client.getName();  }  });  client.setName("Tom");  client.showMyNewName();  Client client2 = new Client(new INameChanger(){  public String changeName(Client client) {  return "Miss." + client.getName();  }  });  client2.setName("Lucy");  client2.showMyNewName();  }  }  

Java 利用接口实现回调相关推荐

  1. Java利用接口计算立体图形的表面积和体积

    利用接口计算立体图形的表面积和体积 /* 设计立体图形接口,包括计算表面积和体积的方法: 设计圆柱体类和圆锥体类,分别实现立体图形接口,计算表面积和体积. */ import java.util.Sc ...

  2. public接口可以被任何一个类实现_一文带你深入Java核心技术:对象克隆+接口与回调,还有这种操作...

    对象克隆 当拷贝一个变量时,原始变量与拷贝变量引用同一个对象,如图6-1所示.这就是说,改变一个变量所引用的对象将会对另一个变量产生影响. Employee original = new Employ ...

  3. java 清空控制台_利用原生库和JNI(Java原生接口)实现H2数据库漏洞利用

    在H2数据库引擎中获取代码执行权限的技术早已是众所周知,但有个要求就是H2能够动态编译Java代码.而本文将向大家展示以前没有公开过的利用H2的方法,并且无需使用Java编译器,即通过原生库和JNI( ...

  4. 高级JAVA - 利用函数式接口实现通用的取并集/交集/差集进阶版

    在前文(高级JAVA - 利用函数式接口实现通用的取并集/交集/差集)中我们实现了利用函数式接口获取交集/差集 , 但是只能全部生成 , 假如我们只需要一个交集的话 , 所有代码仍然会执行一次 . 比 ...

  5. java多态计算几何,通过程序设计几何图形、矩形、圆形、正方形、几种类型,能过利用接口和多态性计算几何图形的面积和周长并显示出来...

    /**利用接口和多态性计算几何图形的面积和周长**/ interface Shape {//声明接口Shape final float PI = 3.14f; // 定义常量圆周率 abstract ...

  6. java多线程查询_利用Java函数式接口处理多线程查询

    Java函数式接口 有且只有一个抽象方法的接口被称为函数式接口. @FunctionalInterface注解: 该注解可用于一个接口的定义上, 一旦使用该注解来定义接口, 编译器将会强制检查该接口是 ...

  7. Java计算各种图形的周长、面积利用接口,多态等知识实现

    知识点 接口,接口的实现 方法的重写 多态的运用 题目 利用接口.类.多态等知识,计算各种图形的周长和面积(圆,长方形,正方形) 解题思路: 创建一个接口Calculate,包含有三个方法, 求解周长 ...

  8. Java中接口、抽象类与内部类学习

    2019独角兽企业重金招聘Python工程师标准>>> Java中接口.抽象类与内部类学习 接口与内部类为我们提供了一种将接口与实现分离的更加结构化的方法. 抽象类和抽象方法 抽象方 ...

  9. Java基础——接口

    一.接口语法 接口的创建 interface //接口不能直接创建对象 public interface grammar {//定义的属性都是公有静态属性(默认也是)String name = &qu ...

最新文章

  1. 《中国人工智能ABC人才发展报告》发布,算法和应用类人才短缺
  2. [.net 面向对象编程基础] (18) 泛型
  3. struts2之请求参数接收
  4. 机器学习笔记(5) KNN算法
  5. 王垠:怎样尊重一个程序员?
  6. helm安装_Helm部署和体验jenkins
  7. JAVA IO系列----ObjectInputStream和ObjectOutputStream类
  8. oracle包同义词报错,Oracle——04同义词与数据库链接
  9. php 赋值给 dom对象,详解PHP原生DOM对象操作XML的方法
  10. Angr安装与使用之使用篇(五)
  11. Hadoop安装教程单机/伪分布式配置
  12. 【病毒查杀】CAD杀毒方法
  13. ADMM 大规模变量优化
  14. 漫画:为什么不能打断程序员?
  15. 【5G之道】第十四章:异构网络部署
  16. 【高德地图API】如何转到高德坐标系?
  17. Mac OS X 背后的故事(三)Mach之父Avie Tevanian 1
  18. HCIP 综合实验(一)
  19. python从业人员工资_会Python的人,毕业后工资到底有多高?
  20. 注册电子邮箱帐号优点

热门文章

  1. Linux系统中重启tomcat的一般步骤
  2. delete archivelog all 无法彻底删除归档日志?
  3. 百个JavaScript函数以及基础写法汇总
  4. Servlet WEB过滤器
  5. 第 4 章 Glance - 022 - 如何使用 OpenStack CLI
  6. LeetCode-17-Letter Combinations of a Phone Number
  7. mp4格式解析、分割
  8. 【编码】对qsort函数的稳定排序优化-京东实习笔试编程题(一)-2016.04.08
  9. 《从零开始学Swift》学习笔记(Day 7)——Swift 2.0中的print函数几种重载形式
  10. android-async-http使用例子