JDK1.7新特性(3):java语言动态性之脚本语言API
简要描述:其实在jdk1.6中就引入了支持脚本语言的API。这使得java能够很轻松的调用其他脚本语言。具体API的使用参考下面的代码:
package com.rampage.jdk7.chapter2; import java.io.FileWriter;
import java.io.IOException; import javax.script.Bindings;
import javax.script.Compilable;
import javax.script.CompiledScript;
import javax.script.Invocable;
import javax.script.ScriptContext;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
import javax.script.SimpleBindings; /**
* 简单的脚本引擎使用方法
*
* @author zyq
*
*/
public class SimpleScriptAPI {
public static void main(String[] args) throws ScriptException, IOException, NoSuchMethodException {
SimpleScriptAPI simpleScriptEngine = new SimpleScriptAPI(); // Part 1: 通用的脚本引擎用法
ScriptEngine engine = simpleScriptEngine.getJavaScriptEngine();
if (engine == null) {
throw new RuntimeException("找不到JavaScript脚本执行引擎!");
}
engine.eval("var a = 12;"); // Part 2: 不同脚本语言与java之间的对象绑定
engine.put("name", "Alex");
engine.eval("var message = 'hello ' + name");
Object message = engine.get("message");
System.out.println(message); // hello Alex // 当然也可以通过SimpleBinds对象来进行变量绑定或者通过脚本引擎的createBindings方法
Bindings bindings = new SimpleBindings();
bindings = engine.createBindings();
bindings.put("hobby1", "java");
bindings.put("hobby2", "dota");
engine.eval("var message2 = 'I like ' + hobby1 + ' and ' + hobby2", bindings);
// 使用binding来绑定的变量只能在脚本语言内部是使用,java语言内获取不到对应的变量
System.out.println(engine.get("message2")); // null
System.out.println(engine.get("hobby1")); // null
System.out.println(engine.get("hobby2")); // null
engine.put("hobby1", "java");
engine.put("hobby2", "dota");
engine.eval("var message2 = 'I like ' + hobby1 + ' and ' + hobby2");
System.out.println(engine.get("message2")); // I like java and dota
System.out.println(engine.get("hobby1")); // java
System.out.println(engine.get("hobby2")); // dota // Part 3: 脚本执行上下文
// ScriptContext的setReader/setWriter/setErrorWriter可以分别设置脚本执行时候的输入来源,输出目的地和错误输出目的地
ScriptContext context = engine.getContext();
context.setWriter(new FileWriter("output.txt"));
engine.eval("var a = 13");
// ScriptContext中也有setAttribute和getAttribute方法来自定义属性。属性有不同的作用域之分。
// 每个作用域都以一个对应的整数表示其查找顺序,该整数越小,说明查找时的顺序更优先。
// 因此在设置属性时需显示的指定所在的作用域,在获取属性的时候可以指定查找的作用域。也可以选择根据作用域优先级
// 自动进行查找。
// 但是脚本执行上下文所能包含的作用域可以通过 getScopes 方法得到而不能随意指定
System.out.println(context.getScopes()); // [100, 200]
// ScriptContext预先定义了两个作用域: ENGINE_SCOPE(当前脚本引擎) 和 GLOBAL_SCOPE(从同一引擎工厂创建出来的所有脚本引擎),前者的优先级更高
context.setAttribute("name", "Alex", ScriptContext.GLOBAL_SCOPE);
context.setAttribute("name", "Bob", ScriptContext.ENGINE_SCOPE);
System.out.println(context.getAttribute("name")); // Bob
// ScriptContext的setbindings方法设置的语言绑定对象会影响到ScriptEngine在执行脚本时的变量解析。
// ScriptEngine的put和get方法所操作的实际上就是ScriptContext中作用域为ENGINE_SCOPE的语言绑定对象。
// 从ScriptContext中得到语言绑定对象之后,可以直接对这个对象进行操作。如果在ScriptEngine的eval中没有
// 指明所使用的语言绑定对象,实际上起作用的是ScriptContext中作用域为ENGINE_SCOPE的语言绑定对象。
Bindings binding1 = engine.createBindings();
binding1.put("name", "Alex");
context.setBindings(binding1, ScriptContext.GLOBAL_SCOPE);
Bindings binding2 = engine.createBindings();
binding2.put("name", "Bob2");
context.setBindings(binding2, ScriptContext.ENGINE_SCOPE);
System.out.println(engine.get("name")); // Bob2
Bindings binding3 = context.getBindings(ScriptContext.ENGINE_SCOPE);
binding3.put("name", "Alex2");
System.out.println(engine.get("name")); // Alex2
context.setAttribute("name", "Bob3", ScriptContext.ENGINE_SCOPE);
System.out.println(engine.get("name")); // Bob3 // Part 4: 脚本的编译
// 脚本语言一般是解释执行的,脚本引擎在运行时需要先解析脚本之后再执行。一般来说
// 通过解释执行的方式运行脚本的速度比先编译再运行会慢一些。所以对于需要多次执行的脚本,我们
// 可以选择先编译,以防止重复解析。不是所有的脚本语言都支持对脚本进行编译,如果脚本支持
// 编译,他会实现 javax.script.Compilable接口。编译的结果用CompiledScript来表示。
if (engine instanceof Compilable) {
CompiledScript script = ((Compilable) engine).compile("var a = 12; b = a * 3;");
script.eval();
} // Part 5: 方法调用
// 有些脚本引擎允许使用者单独调用脚本中的某个方法。支持这种调用方法的脚本引擎可以实现
// javax.script.Invocable 接口。通过Invocable接口既可以调用脚本中的顶层方法,也可一
// 调用对象中的成员方法。如果脚本中的顶层方法或者对象中的成员方法实现了java中的接口,
// 可以通过Invocable接口中的方法来获取及脚本中对应的java接口 的实现对象。这样就可以
// 在java中定义借口,在脚本中实现接口。程序中使用该接口的其他部分代码并不知道接口是
// 由脚本来实现的。
String scriptText = "function greet(name) {return 'hello ' + name; }";
engine.eval(scriptText);
Invocable invocable = (Invocable) engine;
System.out.println(invocable.invokeFunction("greet", "Alex")); // hello Alex
// 如果调用的是脚本中对象的成员方法,则需要用invokeMethod.
scriptText = "var obj = {getGreeting: function(name) {return 'hello ' + name;}};";
engine.eval(scriptText);
Object scope = engine.get("obj");
System.out.println(invocable.invokeMethod(scope, "getGreeting", "Bob")); // hello Bob
// 在脚本中实现接口
scriptText = "function getGreeting(name) {return 'Hello ' + name;}";
engine.eval(scriptText);
Greet greet = invocable.getInterface(Greet.class); // 接口必须是public类型的
System.out.println(greet.getGreeting("KiDe"));
} private ScriptEngine getJavaScriptEngine() {
ScriptEngineManager manager = new ScriptEngineManager();
// PS: 通过脚本引擎管理者来获取对应引擎,有三种方法:一是通过getEngineByName(这时只能是 javascript 或者
// JavaScript)
ScriptEngine engine = manager.getEngineByName("JavaScript");
// 第二种方法是通过 getEngineByExtension (这时候只能是全小写的js)
// engine = manager.getEngineByExtension("js");
// 第三种方法是通过 getEngineByMimeType (这时候也必须是全小写的 text/javascript)
// engine = manager.getEngineByMimeType("text/javascript"); return engine;
}
}
SimpleScriptAPI
 package com.rampage.jdk7.chapter2;
 public interface Greet {
     String getGreeting(String name);
 }
Greet
JDK1.7新特性(3):java语言动态性之脚本语言API的更多相关文章
- JDK1.7新特性(4):java语言动态性之反射API
		
直接通过一个代码示例来熟悉java中通过反射来对构造函数/域以及方法处理的相关API: package com.rampage.jdk7.chapter2; import java.lang.refl ...
 - JDK1.7新特性
		
jdk1.7新特性 1 对集合类的语言支持: 2 自动资源管理: 3 改进的通用实例创建类型推断: 4 数字字面量下划线支持: 5 switch中使用string: 6 二进制字面量: 7 简化可变参 ...
 - jdk1.6新特性
		
1.Web服务元数据 Java 里的Web服务元数据跟微软的方案基本没有语义上的区别,自从JDK5添加了元数据功能(Annotation)之后,SUN几乎重构了整个J2EE体 系, 由于变化很大,干脆 ...
 - JDK1.6新特性,WebService强化
		
Web service是一个平台独立的,松耦合的,自包含的.基于可编程的web的应用程序,可使用开放的XML标准来描述.发布.发现.协调和配置这些应用程序,用于开发分布式的互操作的应用程序. Web ...
 - JDK1.5新特性,基础类库篇,集合框架(Collections)
		
集合框架在JDK1.5中增强特性如下: 一. 新语言特性的增强 泛型(Generics)- 增加了集合框架在编译时段的元素类型检查,节省了遍历元素时类型转换代码量. For-Loop循环(Enhanc ...
 - jdk1.5新特性之-----自动装箱与自动拆箱
		
import java.util.ArrayList; /* jdk1.5新特性之-----自动装箱与自动拆箱. java是面向对象 的语言,任何事物都可以使用类进行描述,sun就使用了 一些类描述j ...
 - JDK1.7新特性(2):异常和可变长参数处理
		
异常 jdk1.7对try--catch--finally的异常处理模式进行了增强,下面我们依次来看增强的方面. 1. 为了防止异常覆盖,给Throwable类增加了addSuppressed方法,可 ...
 - jdk1.8新特性应用之Iterable
		
我们继续看lambda表达式的应用: public void urlExcuAspect(RpcController controller, Message request, RpcCallback ...
 - jdk1.8新特性之lambda表达式
		
lambda表达式其实就是指一个匿名函数,应用最广泛的就是匿名内部类的简化.在jdk1.8之前,我们定义一个匿名内部类可能需要写一大坨代码,现在有了lambda之后,可以写的很简洁了.但不是说lamb ...
 
随机推荐
- windows通过命令方式解压zip文件
			
1.需要下载unzip 地址:http://gnuwin32.sourceforge.net/packages/unzip.htm 下载exe版本 2.安装后将bin目录下的unzip.exe文件放在 ...
 - 加固apk的开发者最常面对的十种问题
			
欢迎访问网易云社区,了解更多网易技术产品运营经验. 因为工信部对移动App应用安全过检要求日益增多,不加固大都达不到工信部的要求,同时开发者加固App大都是为了防止以下10个检测项出现问题,影响App ...
 - jQuery--事件, 事件绑定, 阻止事件冒泡, 事件委托,页面载入后函数
			
1.常用事件, 按住shift键实现同步选择效果,搜索框联想效果 2.阻止事件冒泡 3.事件委托 4.使用 $(document).ready(function (){...}) 实现文件加载完绑定事 ...
 - 深浅copy和浅copy
			
深浅copy 1,先看赋值运算. l1 = [1,2,3,['barry','alex']] l2 = l1 l1[0] = 111 print(l1) # [111, 2, 3, ['barry', ...
 - java中继承的关系
			
当有父子关系的两个类(继承关系),当子类实例化对象的时候 会默认调用父类的无参构造方法,如果有 super()的话,调用的是父类有参的构造方法! 也就是说 父类必须有 有参构造 没有的话super ...
 - Substrings(SPOJ8222) (sam(后缀自动机))
			
You are given a string \(S\) which consists of 250000 lowercase latin letters at most. We define \(F ...
 - Codechef:Fibonacci Number/FN(二次剩余+bsgs)
			
题面 传送门 前置芝士 \(bsgs\),\(Cipolla\) 题解 因为题目保证\(p\bmod 10\)是完全平方数,也就是说\(p\bmod 5\)等于\(1\)或\(-1\),即\(5\)是 ...
 - css元素垂直居中的8中方法
			
1. 通过vertical-align:middle实现CSS垂直居中 通过vertical-align:middle实现CSS垂直居中是最常使用的方法,但是有一点需要格外注意,vertical生效的 ...
 - ES6之新增const命令使用方法
			
hi,我又回来了,今天学习一下const命令. 声明一个常量 const声明一个只读常量,一旦声明,常量的值便不可改变. 例子如下: const food = 12; food = 23; // Un ...
 - [Re:从零开始的分布式] 0.x——分布式基础概念
			
分布式的特点 1. 分布式 2. 对等性 3. 并发性 4. 缺乏全局时钟 5. 故障总是会发生 分布式环境的问题 1. 网络不可靠 2. 网络分区 3. 节点故障 CAP理论 一致性 可用性 分区容 ...