java8 终于来了.函数式接口,lambda表达式期待好久了.新的武器在手,应该能够玩出新花样.javascript
前两天无心中发现java8 中还带了另一个有意思的东西.html
Nashorn 一个javascript引擎.java
这等好玩的东西不把玩一下实在是浪费了.因此直接找到了oracle官方的介绍文档.说实话,文档真给力啊.python
这篇文章是我一边看Oracle官方文档,一边敲代码试验,一边写的,不算是翻译的文档,算是中文版总结文档吧.呵呵.shell
#原文地址:Oracle Nashorn: A Next-Generation JavaScript Engine for the JVMwindows
java7之前,JDK内置了一个基于Mozilla Rhino的javascript脚本引擎.在java8里面,基于JSR292和invokedynamic从新提供了一个新的javascript引擎-Oracle Nashorn.它更符合ECMA标准的javascript规范,并且基于invokedynamic调用拥有更好的性能.ruby
文章使用的是最新的JDK8.因此想用要先装一下.bash
第一个栗子oracle
第一个程序必定是HelloWorld.并且是命令行下面的实现.所以.打开一个命令行吧.函数
若是你的命令行配好了,输入 jjs 回车
就能够看到Nashrn的命令行了.
print("hello halu");
若是你人品没问题,你必定看到输出了...../抠鼻
第二个栗子
命令行下面能够用了,那么抓紧试试用js文件吧.
把下面的代码保存在一个文件里面,个人文件名是halu.js
function SayHi(){ print("hello halu"); } SayHi();
而后打开命令行,cd到文件所在的目录.
windows下面cd有个技巧能够用.在文件夹空白的位置按住shift右击鼠标,菜单中会出如今此处打开命令窗口的选项,通常人我可不告诉他.
命令行下输入 jjs halu.js 就能够看到执行结果了.
第三个栗子
要知道,这但是java8 环境.看下面的例子吧.
var data = [1,2,3,4,5,6,7,8,9,10]; var filtered = data.filter(function(i){ return i%2 == 0; },0); print(filtered); var sumOfFilterd = filtered.reduce(function (acc,next){ return acc + next; },0); print(sumOfFilterd);
看一下执行结果吧.这个例子里面信息量但是巨大的.
Nashorn 只是使用听从 ECMA 规范的javascript语言,在网页上经常使用的对象Nashorn里面并无.好比说 console,window等对象.
命令行执行如下 jjs -help,在帮助中能够看到.
脚本模式颇有趣,你可使用jjs运行使用javascript编写的系统脚本.相似python,ruby,bash脚本.脚本模式有两种扩展:heredocs和shell invocations.
var data = { foo:"bar", time: new Date() }; print("< So...foo = ${data.foo} and the current time is ${data.time} EOF");
使用 jjs -scripting halu.js 执行该脚本.
heredocs 是一种简单的多行文本,使用相似bash的语法.使用 < 符号开始后面跟一个特殊标记.字符串中可使用 ${} 表达式(相似EL表达式).须要注意的是,若是使用单引号引发来的字符串,内部的标示是不会被替换的.
Shell invocations 是容许调用命令行程序.
var lines =\`ls`; print(lines);
这样就能够执行shell命令了.固然windows下面失败....
**注意符号是 ` [波浪线那个键],不是 ' [单引号] ** ,我找了很久才发现.
下面咱们来写一个 java 程序
import javax.script.ScriptEngine; import javax.script.ScriptEngineManager; public class halu{ public static void main(String[] args) throws Throwable{ ScriptEngineManager engineManager = new ScriptEngineManager(); ScriptEngine engine = engineManager.getEngineByName("nashorn"); engine.eval("function sum(a,b){return a+b;}"); System.out.println(engine.eval("sum(1,2);")); } }
这段代码很简单,使用ScriptEngineManager 得到一个 ScriptEngine.而后经过eval函数执行字符串脚本.
Invocable invocable = (Invocable) engine; System.out.println(invocable.invokeFunction("sum",1,3));
engine 也可使用invocable接口调用脚本内的函数.
增长一个 Adder.java 的接口
public interface Adder{ int sum(int a, int b); }
halu类里面
Adder adderaa = invocable.getInterface(Adder.class); System.out.println(""+ adderaa.sum(2,3));
这样能够将javascript的类映射到java的接口上.我的感受这是个很强大的功能.
读取脚本文件执行.使用 java.io.FileReader;
engine.eval(new FileReader("halu.js"));
咱们来使用javascript调用java
print(java.lang.System.currentTimeMillis()); var file = new java.io.File("halu.js"); print(file.getAbsolutePath()); print(file.absolutePath);
使用 jjs 命令执行哦~
集合的使用
var stack = new java.util.LinkedList(); [1, 2, 3, 4].forEach(function(item) { stack.push(item); }); print(stack); print(stack.getClass());
javascript实现java接口
var iterator = new java.util.Iterator({ i: 0, hasNext: function() { return this.i < 10; }, next: function() { return this.i++; } }); print(iterator instanceof Java.type("java.util.Iterator")); while (iterator.hasNext()) { print("-> " + iterator.next()); }
javascript 实现多个接口
var ObjectType = Java.type("java.lang.Object"); var Comparable = Java.type("java.lang.Comparable"); var Serializable = Java.type("java.io.Serializable"); var MyExtender = Java.extend( ObjectType, Comparable, Serializable); var instance = new MyExtender({ someInt: 0, compareTo: function(other) { var value = other["someInt"]; if (value === undefined) { return 1; } if (this.someInt < value) { return -1; } else if (this.someInt == value) { return 0; } else { return 1; } } }); print(instance instanceof Comparable); print(instance instanceof Serializable); print(instance.compareTo({ someInt: 10 })); print(instance.compareTo({ someInt: 0 })); print(instance.compareTo({ someInt: -10 }));
Nashorn 真心好玩.javascript语言自己就有无限可能性,应该能作出来一些好玩的东西.下面就该考虑如何使用Nashorn作点东西了.
#PS: shell invocable 不支持 windows 真心以为坑.....谁要是有办法请留言给我.