BeanShell脚本接口之“傻瓜”适配器(Adapter)和不完整的接口

简介:

更多BeanShell内容请点击此处

在 Java 中为了(处理)拥有多个方法的接口而创建“傻瓜”适配器的情况非常得常见。傻瓜适配器的工作就是带着存根(空方法体)实现接口中的所有方法,允许开发者扩展适配器并且只是重写感兴趣的方法。

我们在之前的讨论中暗示过 BeanShell 可以处理只是实现实际被使用的方法子集的脚本接口,而 BeanShell 的确就是这样。你可以在 BeanShell 中自由地只是编写你期望调用的接口方法的脚本。离开了实际被调用的方法的惩罚是调用者会接收到一个特殊的 run-time 异常: java.lang.reflect.UndeclaredThrowableException。

UndeclaredThrowableException 是 Java 语法 API 中的一个典型,使动态接口成为可能。就是说一个接口抛出一个没有被方法签名指定的检查异常类型。那是在 Java 编译环境中不太会发生的情况。所以 Java 反射 API 通过在这个特殊的未检查(RuntimeException)类型里包装检查异常的方式将它抛出。你可以通过使用 exception 的 getCause() 方法获得隐含的错误,这样做将显示 BeanShell 的 EvalError 异常,报出没有找到正确签名的脚本方法。

invoke() 元方法
BeanShell 为带有大量方法的脚本接口提供一个非常简单的速记机制。你可以在任何脚本上下文中实现特殊方法 invoke(name, args)。invoke() 方法被调用来处理未被定义的接口的任何方法的调用。
示例代码


 
 
  1. mouseHandler = new MouseListener() { 
  2.   mousePressed( event ) { 
  3.     print("mouse button pressed"); 
  4.   } 
  5.   invoke( method, args ) { 
  6.     print("Undefined method of MouseListener interface invoked:" + name +", with args: "+args  ); 
  7.   } 
  8. }; 
  9. JFrame jf = new JFrame(); 
  10. int a10 = Toolkit.getDefaultToolkit().getScreenSize().width; // 取得屏幕长度 
  11. int b10 = Toolkit.getDefaultToolkit().getScreenSize().height; // 取得屏幕宽度 
  12. jf.setLocation((a10 - 500) / 2, (b10 - 300) / 2); // 设定位置(屏幕中心) 
  13. jf.setTitle("窗口"); // 设定标题 
  14. jf.setSize(500, 300); // 设定大小 
  15. jf.setResizable(false); // 设定不能缩放 
  16. jf.setVisible(true); // 设定显示 
  17. jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // 设定在点关闭后关闭窗口 
  18. jf.addMouseListener(mouseHandler); 

运行效果

呈现出的窗口

将你的鼠标移到窗口内,或者点击窗口空白处来观察控制台的变化
 

在上面的例子中我们忽视了 MouseListener 接口里五个方法中的四个方法。他们将会被 invoke() 方法处理,简单地打印方法名和他的参数。不管怎样,既然 mousePressed() 方法被定义了,它就会被接口调用。

这是一个更实际的例子,可谓性手拈来。在解析一个 XML 文档时,让我们使用 invoke() 方法来打印通过 Java SAX API 接口 ContentHandler 调用的方法名称。

示例代码


 
 
  1. import javax.xml.parsers.*; 
  2. import org.xml.sax.InputSource; 
  3. factory = SAXParserFactory.newInstance(); 
  4. saxParser = factory.newSAXParser(); 
  5. parser = saxParser.getXMLReader(); 
  6. parser.setContentHandler( this ); 
  7. invoke( name, args ) { 
  8.   print( name ); 
  9. parser.parse( new InputSource(bsh.args[0]) ); 

通过运行 XML 文件脚本作为参数,我们可以看到几打或者如同这样 SAX API 的方法通过文档的结构被运行起来,无需为它们每个方法写空方法。


 
 
  1. 提示: 
  2. 你可以直接在你自己的范围或者也可以是全局的范围里使用 invoke(name, args)元方法,这样你可以自己任意处理 
  3. “unknown”方法的调用,也许是实现你自己的“虚拟”命令。试着在命令行里打如下的内容: 
  4.  
  5. invoke(name,args) { print("Command: "+name+" invoked!"); } 
  6. noSuchMethod(); // 打印 "Command: noSuchMethod() invoked!" 

运行效果



本文转自 tongqiuyan  51CTO博客,原文链接:http://blog.51cto.com/tongqiuyan/762599


相关文章
|
5月前
|
Java 编译器 Windows
技术笔记:WindowAdapter适配器类
技术笔记:WindowAdapter适配器类
44 0
|
6月前
|
设计模式 算法 C语言
【C/C++ 程序设计】 C++如何适配他人的接口(How to Adapt to Others‘ Interfaces in C++)
【C/C++ 程序设计】 C++如何适配他人的接口(How to Adapt to Others‘ Interfaces in C++)
144 1
|
Linux C语言
Linux驱动 | procfs接口创建
Linux驱动 | procfs接口创建
|
6月前
|
JSON 数据格式
如何创建接口,设计过接口
项目遵循Restful规范设计接口,请求路径基于资源命名,如查询用GET,新增用POST,修改用PUT,删除用DELETE。GET参数通过问号或路径传递,POST/PUT用JSON。统一的接口规范规定:返回数据多时,用VO过滤或整合数据。
44 0
|
数据挖掘 API PHP
Playfab开发(一)如何调用PlayFab接口
Playfab开发(一)如何调用PlayFab接口
|
jenkins 测试技术 持续交付
python接口自动化(三十五)-封装与调用--流程类接口关联(详解)
流程相关的接口,主要用 session 关联,如果写成函数(如上篇),s 参数每个函数都要带,每个函数多个参数,这时候封装成类会更方便。在这里我们还是以博客园为例,带着小伙伴们实践一下。
385 0
python接口自动化(三十五)-封装与调用--流程类接口关联(详解)
|
XML JSON 数据可视化
这么好用的接口工具,请允许我油腻一次!
年前的时候,测试负责人刘哥说“为了保证每次迭代质量上线,除了原有的功能(UI)层面的测试以外,必须把API接口自动化测试提上日程。
|
XML SQL JSON
3 行代码写出 8 个接口,牛逼啊,这也行?
肯定有不少人会想:这怎么可能呢? 就算用几乎零配置的 SpringBoot,写一个最简单的接口也得有 3 行代码啊!
166 0
3 行代码写出 8 个接口,牛逼啊,这也行?