深入BeanShell脚本对象

简介:

更多详情请见此处

使用 BeanShell 的许多朋友使用它来编写与已经存在的 Java 类或者 API 作业的脚本,或者为了他们自己的应用在运行时在没有其他编译器的帮助下执行其他种类动态的活动。通常这意味着编写相对非结构化的代码——比如,包含在一个 单独的脚本文件或者 eval() 语句里的一系列方法调用或者循环。在之前的章节中我们看到 BeanShell 也具有脚本方法的能力,就像 Java 一样。创建方法以及新的 BeanShell 命令(仅仅是他们自己文件中的方法)是组织你的脚本成为可重用、可维护组件的自然进程。

方 法和结构化的程序设计当然在于对象以及面向对象编程完整的程度。在 Java 中对象是类的产物。虽然 BeanShell 和标准的 Java 语法是兼容的,包括语句、表达式以及方法,但你仍然不能在 BeanShell 中编写新的 Java 类的脚本。但是,BeanShell 允许你编写像“闭合方法”的脚本对象,类似在 Perl 5.x、JavaScript 还有其他对象——可以写脚本的语言中的做法。这类脚本对象(我们马上就会描述)的风格简单而且从脚本方法的风格自然流传下来。你马上会看到这种语法,是标 准 Java 使用“this”引用指向一个对象的概念的直接扩展。


 
 
  1. 注意: 
  2. 在标准 Java 中,一个方法在一个对象(一个实例化的方法)里可以使用专门的变量“this”指向这个封闭 
  3. 的对象。 
  4.  
  5. // MyClass.java 
  6. MyClass { 
  7. Object getObject() { 
  8. return this; // 返回对象的一个引用 
  9.  
  10. 在上面的例子里,MyClass 的 getObject() 方法返回自己对象实例(MyClass 对象的实例)的一个引用。 

“this”引用
跟多数的语言一样,BeanShell 里的一个执行的方法有它自己持有参数(传值参数)变量和本地声明变量的“本地化”范围。在下面的代码段中,在 foo() 方法中我们会使用到的任何变量通常只在 foo() 当中以及一个特定的 foo() 方法调用的生存期内可见。
示例代码


 
 
  1. // 定义 foo() 方法: 
  2. foo() { 
  3. int bar = 42; 
  4. print( bar ); 
  5. // 调用 foo() 方法: 
  6. foo(); // 打印 42 
  7. print( bar ); // Error, bar 在此未定义 

运行效果

在上面的例子中,变量"bar"属于方法foo(),因此在方法调用的外面是不可用的——方法退出时变量就会被处理掉,如标准的 Java 本地变量一样。

现在转换一个视角——在 BeanShell 里你可以选择通过专门的“this”引用在一个方法调用退出之后对该作用域“抓住不放”。就像在 Java 中一样,“this”指向当前对象的上下文。唯一不同过的地方就是在这种情况下该上下文只与该方法有关联,却不是一个类的实例。

在方法返回之后保存“this”引用,使用标准 Java 记号“.”你可以继续指向在该方法中定义的变量:


 
 
  1. foo() { 
  2. int bar = 42; 
  3. return this; 
  4. fooObject = foo(); 
  5. print( fooObject.bar ); // 打印 42! 

运行效果

在上面的例子中,foo() 方法返回值(“this”引用)可以看做是一个“foo”对象的实例。每一次 foo() 方法调用会创建一个新的对象;foo() 此时不仅仅是一个方法,还是对象构造的一种形式。

上面案例中的 foo 对象甚至可以说不是一个对象,说是一个构造器更合适。它包含变量(bar)但没有“行为”。
下一个视角,我们会介绍 BeanShell 方法也允许包含其他方法:


 
 
  1. foo() { 
  2.     bar() { 
  3.       ... 
  4.     } 

脚本方法可以通过这种方式定义任意数量的嵌套方法,可以是任意深度的。这些方法是方法的“本地”调用。

BeanShell 方法闭合范围内的语句和表达式可以叫做“本地”方法,就像任何其他方法一样。(局部地定义的方法覆盖外部的——在 Java 里多数方法像本地变量那样隐藏了实例变量。)闭合的方法并不直接在闭合方法外部可见。然而,正如你希望的那样,你可以像对 Java 对象那样通过一个适当的对象引用来调用它们:


 
 
  1. foo() { 
  2. int a = 42; 
  3. bar() { 
  4. print("The bar is open!"); 
  5. bar(); 
  6. return this; 
  7. // 构造 foo 对象 
  8. fooObject = foo(); // 打印 "the bar is open!" 
  9. // 打印 foo 对象的一个变量 
  10. print ( fooObject.a ); // 42 
  11. // 使用 foo 对象调用一个方法 
  12. fooObject.bar(); // 打印 "the bar is open!" 

运行效果


在方法里的方法声明在块状的结构中,表现得就像它们直接被声明在该方法里一样。换言之,没有本地块方法。
示例代码


 
 
  1. foo() { 
  2.     bar() { } 
  3.       if ( true ) { 
  4.         bar2() { } 
  5.     } 
  6.     return this; 

在上面的例子中,方法 bar() 和 bar2() 都被定义在 foo() 里面。

下一章节我们回到变量作用域的话题中来,并更加深入地探讨如何使用脚本方法和对象。



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


相关文章
|
2月前
|
机器学习/深度学习 JSON 监控
国内最大的MCP中文社区来了,4000多个服务等你体验
国内最大的MCP中文社区MCPServers来了!平台汇聚4000多个服务资源,涵盖娱乐、监控、云平台等多个领域,为开发者提供一站式技术支持。不仅有丰富的中文学习资料,还有详细的实战教程,如一键接入MCP天气服务等。MCPServers专注模块稳定性和实用性,经过99.99% SLA认证,是高效开发的理想选择。立即访问mcpservers.cn,开启你的开发之旅!
2048 16
|
7月前
|
C语言
【c语言】动态内存管理
本文介绍了C语言中的动态内存管理,包括其必要性及相关的四个函数:`malloc`、``calloc``、`realloc`和`free`。`malloc`用于申请内存,`calloc`申请并初始化内存,`realloc`调整内存大小,`free`释放内存。文章还列举了常见的动态内存管理错误,如空指针解引用、越界访问、错误释放等,并提供了示例代码帮助理解。
166 3
|
11月前
|
机器学习/深度学习 人工智能 算法
智能医疗新时代:AI在诊断与治疗中的深度探索
【7月更文第19天】随着人工智能技术的飞速发展,其在医疗领域的应用正逐渐成为推动行业变革的关键力量。从精准的医学影像分析到疾病的早期预测,再到加速药物研发进程,AI技术正以前所未有的方式辅助医生制定更加个性化、高效的治疗方案,为患者带来新的希望。本文将深入探讨AI在健康医疗中的三大核心应用领域:医学影像分析、疾病预测与药物研发,并通过代码示例展示其技术实践。
691 4
|
9月前
|
安全 Java API
【Java炸裂更新】JDK 22:区域锚定引领G1垃圾回收革命,性能飙升新高度!
【9月更文挑战第6天】JDK 22的发布,标志着Java在性能优化和垃圾回收技术上的又一次重大突破。区域锚定技术的引入,不仅提升了G1垃圾收集器的效率,也为Java应用的性能提升注入了新的动力。随着Java生态的不断发展和完善,我们有理由相信,Java将继续在编程界保持其铁打英雄的地位,为开发者们带来更多惊喜和可能。 让我们共同期待,Java在JDK 22的引领下,开启一个全新的性能飙升时代!
159 17
|
10月前
|
Ruby
GitLab: Push operation timed out
本文描述了在推送AOSP源码到GitLab时遇到的超时问题,并提供了通过在GitLab服务器上禁用LFS检查功能来解决这个问题的方法。
201 1
|
API 数据库
什么是营销服务?服务营销简易理解
营销服务是企业推广产品、吸引客户和提升销售额的关键手段,包括市场调研、广告、促销和客户服务。线上营销如网络广告和社交媒体推广,线下营销如门店促销和展览会,帮助企业了解市场、塑造品牌形象、增加销量。通过精准营销、优化服务和强化品牌宣传可提升营销效果。AokSend提供高效验证码发信服务,助力企业营销。企业需不断创新营销策略以适应竞争环境。
|
数据采集 消息中间件 存储
Flume 快速入门【概述、安装、拦截器】
Apache Flume 是一个开源的数据采集工具,用于从各种数据源(如日志、网络数据、消息队列)收集大规模数据,并将其传输和加载到数据存储系统(如 HDFS、HBase、Hive)。Flume 由数据源(Source)、通道(Channel)、拦截器(Interceptor)和接收器(Sink)组成,支持灵活配置以适应不同的数据流处理需求。安装 Flume 包括解压软件包、配置环境变量和调整日志及内存设置。配置文件定义数据源、通道、拦截器和接收器,拦截器允许预处理数据。Flume 适用于构建数据管道,整合分散数据到中心存储系统,便于分析和报告。
1979 3
|
API 开发工具 Android开发
简述大疆无人机对接
【2月更文挑战第7天】本文介绍了对接大疆无人机的主要目的,包括实时画面获取、飞行数据监测、操控飞行、媒体管理和业务功能开发等,并列举了多种开发接口如MobileSDK、UXSDK、云开发API等。重点讨论了MobileSDK在Android平台的应用,包括SDK集成步骤、直播推流和获取飞机实时数据的细节。另外,UXSDK用于加速应用开发,提供预设UI组件。上云API则简化了无人机与第三方云平台的集成,支持MQTT、HTTPS和WebSocket协议,适用于行业级无人机。对接流程涉及Pilot2和Dock的配置,以及数据传输和业务功能处理。文章还提及了如何对接多个飞机的方法。
7945 0
简述大疆无人机对接
|
Linux
无敌解决GitHub无法ping通也无法登录的问题无敌解决idea连接GitHub提示Invalid authentication data. Connection reset
无敌解决GitHub无法ping通也无法登录的问题无敌解决idea连接GitHub提示Invalid authentication data. Connection reset
528 1
|
缓存 Ubuntu 关系型数据库
在 Ubuntu 中如何完全卸载 MySQL 服务器?
在 Ubuntu 中如何完全卸载 MySQL 服务器?
719 1