【JDK8】Nashorn 與 Java API(二)
在 Nashorn 與 Java API(一) 中介紹了一些如何撰寫 JavaScript 來使用 Java API,語言本身並不是一對一,因而若要進一步使用 Java 的一些特性,就得有一些額外的對應方式。 指定重載方法實際上方法在 JavaScript 不過是個物件上的特性,為函式實例,因此,除了使用 var System = Java.type('java.lang.System'); System.out.println('Hello, World'); // Hello, World System.out['println']('Hello, World'); // Hello, World Java 中支援重載(Overload)方法,例如, var System = Java.type('java.lang.System'); System.out['println'](3.14); // 3.14 System.out['println(double)'](3.14); // 3.14 System.out['println(int)'](3.14); // 3 實例方法也可以使用這種方式: var PrintStream = Java.type('java.io.PrintStream'); var file = new PrintStream('test.txt'); file['println(int)'](3.14); // test.txt 中只存 3 這個數值 file.close(); JavaImporter、importPackage、 importClassJava 中有 var PrintStream = Java.type('java.io.PrintStream'); 如果想同時將數個類別或套件放在某個名稱空間下,可以使用 var commons = new JavaImporter(java.util, java.lang); with(commons) { var lt = Arrays.asList(1, 2, 3); System.out.println(lt); // [1, 2, 3] } Nashorn 內建了 mozilla_compat.js,可以使用 load('nashorn:mozilla_compat.js'); importClass(java.lang.System); importPackage(java.util); System.out.println('Hello, World'); // Hello, World var lt = Arrays.asList(1, 2, 3); System.out.println(lt); // [1, 2, 3] 實作介面如果想要實作介面,可以使用 load('nashorn:mozilla_compat.js'); importPackage(java.lang); var RunDemo = Java.extend(Runnable, { run: function() { [1, 2, 3].forEach(print); } }); var th = new Thread(new RunDemo()); th.start(); th.join(); 不使用 load('nashorn:mozilla_compat.js'); importPackage(java.lang); var r = new Runnable { run: function() { [1, 2, 3].forEach(print); } }; var th = new Thread(r); th.start(); th.join(); 如果方法的參數型態是個只具備單一抽象方法的介面,可以直接使用函式實作。例如: var IntStream = Java.type("java.util.stream.IntStream"); var sum = IntStream.of(1, 2, 3, 4, 5, 6) .filter(function(elem) { return elem > 2; }) .sum(); print(sum); // 18 繼承類別如果是要繼承抽象類別並實作抽象方法,方式與實作介面是類似的: load('nashorn:mozilla_compat.js'); importPackage(java.util); var r = new TimerTask { run: function() { [1, 2, 3].forEach(print); } }; r.run(); var DemoTask = Java.extend(TimerTask, { run: function() { [1, 2, 3].forEach(print); } }); new DemoTask().run(); 然而,如果是繼承非抽象類別,就必須使用 load('nashorn:mozilla_compat.js'); importPackage(java.lang); var DemoThread1 = Java.extend(Thread, { run: function() { [1, 2, 3].forEach(print); } }); new DemoThread1().run(); var DemoThread2 = Java.extend(Thread); (new DemoThread2 { run: function() { [1, 2, 3].forEach(print); } }).run(); 實際上, load('nashorn:mozilla_compat.js'); importPackage(java.lang); var DemoThread1 = Java.extend(Thread, { run: function() { [1, 2, 3].forEach(print); } }); var DemoThread2 = Java.extend(Thread, { run: function() { [1, 2, 3].forEach(print); } }); System.out.println(new DemoThread1().getClass() === new DemoThread2().getClass()); // false var DemoThread = Java.extend(Thread); var th1 = new DemoThread { run: function() { [1, 2, 3].forEach(print); } }; var th2 = new DemoThread { run: function() { [1, 2, 3].forEach(print); } }; System.out.println(th1.getClass() === th2.getClass()); // true 呼叫父類別方法如果想呼叫父類別建構式並同時重新實作某方法,可以如下: load('nashorn:mozilla_compat.js'); importPackage(java.lang); var Th = Java.extend(Thread); var r = function() { [1, 2, 3].forEach(function(elem) { print(elem); }); }; var th1 = new Th(r) { run : function() { Java.super(th1).run(); [4, 5, 6].forEach(function(elem) { print(elem); }); } }; th1.start(); th1.join(); 上面的範例也示範了 從 Java 中執行 JavaScript要在 Java 中使用 Nashorn 執行 JavaScript 的話,可以如下取得 Nashorn 引擎: ScriptEngineManager factory = new ScriptEngineManager(); ScriptEngine engine = factory.getEngineByName("nashorn"); engine.eval("print('Hello, World!')"); engine.eval(new FileReader("C:\\workspace\\hello.js")); 這是 JSR 223: Scripting for the Java Platform 規範中的東西,你可以在 Oracle 的 Scripting for the Java Platform 找到相關資訊。 實際上,這兩篇〈Nashorn 與 Java API〉的內容,在 Oracle Java Platform, Standard Edition Java Scripting Programmer’s Guide 中 3 Using Java From Scripts 就有談到,如果想要瞭解更多如何在 Java 中呼叫 JavaScript,可以進一步參考 2 The Java Scripting API。 專門說明 Nashorn 的 Oracle 文件,則可以在 Java Platform, Standard Edition Nashorn User’s Guide 找到。 |