docs/JavaScriptingProgrammersGuide.html

Wed, 15 May 2013 14:54:28 +0200

author
attila
date
Wed, 15 May 2013 14:54:28 +0200
changeset 267
b37eb709ae27
parent 182
e7e82c1e9aed
child 279
1fd18f40ab52
permissions
-rw-r--r--

8014646: Update the Java interop documentation in the Java Scripting Programmer's Guide
Reviewed-by: jlaskey, hannesw, lagergren

katleman@182 1 <!--
katleman@182 2 Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
katleman@182 3 DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
katleman@182 4
katleman@182 5 This code is free software; you can redistribute it and/or modify it
katleman@182 6 under the terms of the GNU General Public License version 2 only, as
katleman@182 7 published by the Free Software Foundation. Oracle designates this
katleman@182 8 particular file as subject to the "Classpath" exception as provided
katleman@182 9 by Oracle in the LICENSE file that accompanied this code.
katleman@182 10
katleman@182 11 This code is distributed in the hope that it will be useful, but WITHOUT
katleman@182 12 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
katleman@182 13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
katleman@182 14 version 2 for more details (a copy is included in the LICENSE file that
katleman@182 15 accompanied this code).
katleman@182 16
katleman@182 17 You should have received a copy of the GNU General Public License version
katleman@182 18 2 along with this work; if not, write to the Free Software Foundation,
katleman@182 19 Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
katleman@182 20
katleman@182 21 Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
katleman@182 22 or visit www.oracle.com if you need additional information or have any
katleman@182 23 questions.
katleman@182 24 -->
sundar@68 25 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
sundar@68 26 <html class=" regenabled gecko radius jsenabled regloaded" xmlns="http://www.w3.org/1999/xhtml"><head>
sundar@68 27 <meta http-equiv="content-type" content="text/html; charset=ISO-8859-1">
sundar@68 28 <title>Java Scripting Programmer's Guide</title>
sundar@68 29
sundar@68 30 <!-- ============ -->
sundar@68 31 <!-- MAIN CONTENT -->
sundar@68 32 <!-- ============ -->
sundar@68 33 <table summary="layout" border="0" width="100%">
sundar@68 34 <tbody><tr>
sundar@68 35 <td>
sundar@68 36
sundar@68 37 <div id="sharepage" class="smallpagetitle"><h1>Java Scripting Programmer's Guide</h1><div class="sharepage"> <div class="sharepagew1 share-mailto"> <table summary="" cellpadding="0" cellspacing="0"><tbody><tr> <td id="share-mailto"><a href="mailto:?subject=Java%20Documentation%20Page:%20Java%20Scripting%20Programmer%27s%20Guide&amp;body=Check%20out%20this%20page:%20%0A%0Ahttp%3A%2F%2Fdocs.oracle.com%2Fjavase%2F6%2Fdocs%2Ftechnotes%2Fguides%2Fscripting%2Fprogrammer_guide%2Findex.html" class="sharelink mailto" title="Email this page to a friend"></a></td> <td id="share-technorati"><a href="http://technorati.com/search/http%3A%2F%2Fdocs.oracle.com%2Fjavase%2F6%2Fdocs%2Ftechnotes%2Fguides%2Fscripting%2Fprogrammer_guide%2Findex.html" class="sharelink technorati" title="See who links to this page on Technorati"></a></td> <td id="share-delicious"><a href="http://del.icio.us/post?v=4;url=http%3A%2F%2Fdocs.oracle.com%2Fjavase%2F6%2Fdocs%2Ftechnotes%2Fguides%2Fscripting%2Fprogrammer_guide%2Findex.html;title=Java%20Scripting%20Programmer%27s%20Guide" class="sharelink delicious" title="Bookmark this page in del.icio.us"></a></td> <td id="share-digg"><a href="http://digg.com/submit?phase=2&amp;url=http%3A%2F%2Fdocs.oracle.com%2Fjavase%2F6%2Fdocs%2Ftechnotes%2Fguides%2Fscripting%2Fprogrammer_guide%2Findex.html&amp;title=Java%20Scripting%20Programmer%27s%20Guide" class="sharelink digg" title="Submit this page to Digg"></a></td> <td id="share-slashdot"><a href="http://slashdot.org/bookmark.pl?title=Java%20Scripting%20Programmer%27s%20Guide&amp;url=http%3A%2F%2Fdocs.oracle.com%2Fjavase%2F6%2Fdocs%2Ftechnotes%2Fguides%2Fscripting%2Fprogrammer_guide%2Findex.html" class="sharelink slashdot" title="Submit this page to Slashdot"></a></td> <td id="share-blank"> </td></tr></tbody></table></div></div></div>
sundar@68 38
sundar@68 39 </td>
sundar@68 40 </tr>
sundar@68 41 </tbody></table>
sundar@68 42 <!-- Body text begins here -->
sundar@68 43 <ul>
sundar@68 44 <li><span><a href="#who">Who is the Java Scripting API
sundar@68 45 For?</a></span></li>
sundar@68 46 <li><span><a href="#package">Scripting Package</a></span></li>
sundar@68 47 <li><span><a href="#examples">Examples</a></span>
sundar@68 48 <ul>
sundar@68 49 <li><span><a href="#helloworld">"Hello, World"</a></span></li>
sundar@68 50 <li><span><a href="#evalfile">Evaluating a Script
sundar@68 51 File</a></span></li>
sundar@68 52 <li><span><a href="#scriptvars">Script Variables</a></span></li>
sundar@68 53 <li><span><a href="#invoke">Invoking Script Functions and
sundar@68 54 Methods</a></span></li>
sundar@68 55 <li><span><a href="#interfaces">Implementing Java Interfaces by
sundar@68 56 Scripts</a></span></li>
sundar@68 57 <li><span><a href="#scopes">Multiple Scopes for
sundar@68 58 Scripts</a></span></li>
sundar@68 59 </ul>
sundar@68 60 </li>
sundar@68 61 <li><span><a href="#jsengine">JavaScript Script
sundar@68 62 Engine</a></span></li>
sundar@68 63 <li><span><a href="#jstojava">JavaScript to Java
sundar@68 64 Communication</a></span>
sundar@68 65 <ul>
sundar@68 66 <li><span><a href="#jsjavaclass">Accessing Java
sundar@68 67 Classes</a></span></li>
sundar@68 68 <li><span><a href="#jsimport">Importing Java Packages,
sundar@68 69 Classes</a></span></li>
sundar@68 70 <li><span><a href="#jsarrays">Creating, Converting and Using Java
sundar@68 71 Arrays</a></span></li>
sundar@68 72 <li><span><a href="#jsimplement">Implementing Java
sundar@68 73 Interfaces</a></span></li>
attila@267 74 <li><span><a href="#jsextendabstract">Extending Abstract Java Classes
attila@267 75 </a></span></li>
attila@267 76 <li><span><a href="#jsextendconcrete">Extending Concrete Java Classes
attila@267 77 </a></span></li>
attila@267 78 <li><span><a href="#jsimplementmultiple">Implementing Multiple Java Interfaces
attila@267 79 </a></span></li>
attila@267 80 <li><span><a href="#classBoundImplementations">Class-Bound Implementations
sundar@68 81 </a></span></li>
sundar@68 82 <li><span><a href="#jsoverload">Overload Resolution</a></span></li>
attila@267 83 <li><span><a href="#dataTypeMapping">Mapping of Data Types Between Java
attila@267 84 and JavaScript</a></span></li>
attila@267 85
attila@267 86
attila@267 87
sundar@68 88 </ul>
sundar@68 89 </li>
sundar@68 90 <li><span><a href="#engineimpl">Implementing Your Own Script
sundar@68 91 Engine</a></span></li>
sundar@68 92 <li><span><a href="#refs">References</a></span></li>
sundar@68 93 </ul>
sundar@68 94 <span><a name="who" id="who"></a></span>
sundar@68 95 <h2><span>Who is the Java Scripting API For?</span></h2>
sundar@68 96 <span>Some useful characteristics of scripting languages
sundar@68 97 are:</span>
sundar@68 98 <ul>
sundar@68 99 <li><span><b>Convenience</b>: Most scripting languages are
sundar@68 100 dynamically typed. You can usually create new variables without
sundar@68 101 declaring the variable type, and you can reuse variables to store
sundar@68 102 objects of different types. Also, scripting languages tend to
sundar@68 103 perform many type conversions automatically, for example,
sundar@68 104 converting the number 10 to the text "10" as necessary.</span></li>
sundar@68 105 <li><span><b>Developing rapid prototypes</b>: You can avoid the
sundar@68 106 edit-compile-run cycle and just use edit-run!</span></li>
sundar@68 107 <li><span><b>Application extension/customization</b>: You can
sundar@68 108 "externalize" parts of your application - like configuration
sundar@68 109 scripts, business logic/rules and math expressions for financial
sundar@68 110 applications.</span></li>
sundar@68 111 <li><span><b>"Command line" shells for applications</b> -for
sundar@68 112 debugging, runtime/deploy time configuration etc. Most applications
sundar@68 113 have a web-based GUI configuaration tool these days. But
sundar@68 114 sysadmins/deployers frequently prefer command line tools. Instead
sundar@68 115 of inventing ad-hoc scripting language for that purpose, a
sundar@68 116 "standard" scripting language can be used.</span></li>
sundar@68 117 </ul>
sundar@68 118 <p><span>The Java<font size="-1"><sup>TM</sup></font> Scripting API
sundar@68 119 is a scripting language indepedent framework for using script
sundar@68 120 engines from Java code. With the Java Scripting API, it is possible
sundar@68 121 to write customizable/extendable applications in the Java language
sundar@68 122 and leave the customization scripting language choice to the end
sundar@68 123 user. The Java application developer need not choose the extension
sundar@68 124 language during development. If you write your application with
sundar@68 125 JSR-223 API, then your users can use any JSR-223 compliant
sundar@68 126 scripting language.</span></p>
sundar@68 127 <hr>
sundar@68 128 <span><a name="package" id="package"></a></span>
sundar@68 129 <h2><span>Scripting Package</span></h2>
sundar@68 130 <p><span>The Java Scripting functionality is in the <code><a href="http://docs.oracle.com/javase/6/docs/api/javax/script/package-summary.html">javax.script</a></code>
sundar@68 131 package. This is a relatively small, simple API. The starting point
sundar@68 132 of the scripting API is the <code>ScriptEngineManager</code> class.
sundar@68 133 A ScriptEngineManager object can discover script engines through
sundar@68 134 the jar file service discovery mechanism. It can also instantiate
sundar@68 135 ScriptEngine objects that interpret scripts written in a specific
sundar@68 136 scripting language. The simplest way to use the scripting API is as
sundar@68 137 follows:</span></p>
sundar@68 138 <ol>
sundar@68 139 <li><span>Create a <code>ScriptEngineManager</code>
sundar@68 140 object.</span></li>
sundar@68 141 <li><span>Get a <code>ScriptEngine</code> object from the
sundar@68 142 manager.</span></li>
sundar@68 143 <li><span>Evaluate script using the <code>ScriptEngine</code>'s
sundar@68 144 <code>eval</code> methods.</span></li>
sundar@68 145 </ol>
sundar@68 146 <p><span>Now, it is time to look at some sample code. While it is
sundar@68 147 not mandatory, it may be useful to know a bit of JavaScript to read
sundar@68 148 these examples.</span></p>
sundar@68 149 <hr>
sundar@68 150 <span><a name="examples" id="examples"></a></span>
sundar@68 151 <h2><span>Examples</span></h2>
sundar@68 152 <span><a name="helloworld" id="helloworld"></a></span>
sundar@68 153 <h3><span>"Hello, World"</span></h3>
sundar@68 154 <p><span>From the <code>ScriptEngineManager</code> instance, we
sundar@68 155 request a JavaScript engine instance using
sundar@68 156 <code>getEngineByName</code> method. On the script engine, the
sundar@68 157 <code>eval</code> method is called to execute a given String as
sundar@68 158 JavaScript code! For brevity, in this as well as in subsequent
sundar@68 159 examples, we have not shown exception handling. There are checked
sundar@68 160 and runtime exceptions thrown from <code>javax.script</code> API.
sundar@68 161 Needless to say, you have to handle the exceptions
sundar@68 162 appropriately.</span></p>
sundar@68 163 <pre>
sundar@68 164 <span><code>
sundar@68 165 // <a href="source/EvalScript.java">EvalScript.java</a>
sundar@68 166
sundar@68 167 import javax.script.*;
sundar@68 168 public class EvalScript {
sundar@68 169 public static void main(String[] args) throws Exception {
sundar@68 170 // create a script engine manager
sundar@68 171 <span class="classref">ScriptEngineManager</span> factory = new ScriptEngineManager();
sundar@68 172 // create a JavaScript engine
sundar@68 173 <span class="classref">ScriptEngine</span> engine = factory.<span class="methodref">getEngineByName</span>("nashorn");
sundar@68 174 // evaluate JavaScript code from String
sundar@68 175 engine.<span class="methodref">eval</span>("print('Hello, World')");
sundar@68 176 }
sundar@68 177 }
sundar@68 178 </code></span>
sundar@68 179 </pre>
sundar@68 180 <hr>
sundar@68 181 <a name="evalfile" id="evalfile"></a>
sundar@68 182 <h3>Evaluating a Script File</h3>
sundar@68 183 <p>In this example, we call the <code>eval</code> method that
sundar@68 184 accepts <code>java.io.Reader</code> for the input source. The
sundar@68 185 script read by the given reader is executed. This way it is
sundar@68 186 possible to execute scripts from files, URLs and resources by
sundar@68 187 wrapping the relevant input stream objects as readers.</p>
sundar@68 188 <pre>
sundar@68 189 <code>
sundar@68 190 // <a href="source/EvalFile.java">EvalFile.java</a>
sundar@68 191
sundar@68 192 import javax.script.*;
sundar@68 193
sundar@68 194 public class EvalFile {
sundar@68 195 public static void main(String[] args) throws Exception {
sundar@68 196 // create a script engine manager
sundar@68 197 <span class="classref">ScriptEngineManager</span> factory = new ScriptEngineManager();
sundar@68 198 // create JavaScript engine
sundar@68 199 <span class="classref">ScriptEngine</span> engine = factory.<span class="methodref">getEngineByName</span>("nashorn");
sundar@68 200 // evaluate JavaScript code from given file - specified by first argument
sundar@68 201 engine.<span class="methodref">eval</span>(new java.io.FileReader(args[0]));
sundar@68 202 }
sundar@68 203 }
sundar@68 204 </code>
sundar@68 205 </pre>
sundar@68 206 Let us assume that we have the file named <a href="source/test.js">test.js</a> with the
sundar@68 207 following text:
sundar@68 208 <pre><code>
sundar@68 209 print("This is hello from test.js");
sundar@68 210 </code>
sundar@68 211 </pre>
sundar@68 212 We can run the above Java as
sundar@68 213 <pre><code>
sundar@68 214 java EvalFile test.js
sundar@68 215 </code>
sundar@68 216 </pre>
sundar@68 217 <hr>
sundar@68 218 <a name="scriptvars" id="scriptvars"></a>
sundar@68 219 <h3>Script Variables</h3>
sundar@68 220 <p>When you embed script engines and scripts with your Java
sundar@68 221 application, you may want to expose your application objects as
sundar@68 222 global variables to scripts. This example demonstrates how you can
sundar@68 223 expose your application objects as global variables to a script. We
sundar@68 224 create a <code>java.io.File</code> in the application and expose
sundar@68 225 the same as a global variable with the name "file". The script can
sundar@68 226 access the variable - for example, it can call public methods on
sundar@68 227 it. Note that the syntax to access Java objects, methods and fields
sundar@68 228 is dependent on the scripting language. JavaScript supports the
sundar@68 229 most "natural" Java-like syntax.</p>
sundar@68 230 <pre><code>
sundar@68 231 // <a href="source/ScriptVars.java">ScriptVars.java</a>
sundar@68 232
sundar@68 233 import javax.script.*;
sundar@68 234 import java.io.*;
sundar@68 235
sundar@68 236 public class ScriptVars {
sundar@68 237 public static void main(String[] args) throws Exception {
sundar@68 238 ScriptEngineManager manager = new ScriptEngineManager();
sundar@68 239 ScriptEngine engine = manager.getEngineByName("nashorn");
sundar@68 240
sundar@68 241 File f = new File("test.txt");
sundar@68 242 // expose File object as variable to script
sundar@68 243 engine.<span class="methodref">put</span>("file", f);
sundar@68 244
sundar@68 245 // evaluate a script string. The script accesses "file"
sundar@68 246 // variable and calls method on it
sundar@68 247 engine.eval("print(file.getAbsolutePath())");
sundar@68 248 }
sundar@68 249 }
sundar@68 250
sundar@68 251 </code>
sundar@68 252 </pre>
sundar@68 253 <hr>
sundar@68 254 <a name="invoke" id="invoke"></a>
sundar@68 255 <h3>Invoking Script Functions and Methods</h3>
sundar@68 256 <p>Sometimes you may want to call a specific scripting function
sundar@68 257 repeatedly - for example, your application menu functionality might
sundar@68 258 be implemented by a script. In your menu's action event handler you
sundar@68 259 may want to call a specific script function. The following example
sundar@68 260 demonstrates invoking a specific script function from Java
sundar@68 261 code.</p>
sundar@68 262 <pre><code>
sundar@68 263 // <a href="source/InvokeScriptFunction.java">InvokeScriptFunction.java</a>
sundar@68 264
sundar@68 265 import javax.script.*;
sundar@68 266
sundar@68 267 public class InvokeScriptFunction {
sundar@68 268 public static void main(String[] args) throws Exception {
sundar@68 269 ScriptEngineManager manager = new ScriptEngineManager();
sundar@68 270 ScriptEngine engine = manager.getEngineByName("nashorn");
sundar@68 271
sundar@68 272 // JavaScript code in a String
sundar@68 273 String script = "function hello(name) { print('Hello, ' + name); }";
sundar@68 274 // evaluate script
sundar@68 275 engine.eval(script);
sundar@68 276
sundar@68 277 // <code>javax.script.Invocable</code> is an optional interface.
sundar@68 278 // Check whether your script engine implements it or not!
sundar@68 279 // Note that the JavaScript engine implements Invocable interface.
sundar@68 280 <span class="classref">Invocable</span> inv = (Invocable) engine;
sundar@68 281
sundar@68 282 // invoke the global function named "hello"
sundar@68 283 inv.<span class="methodref">invokeFunction</span>("hello", "Scripting!!" );
sundar@68 284 }
sundar@68 285 }
sundar@68 286
sundar@68 287 </code>
sundar@68 288 </pre>
sundar@68 289 <p>If your scripting language is object based (like JavaScript) or
sundar@68 290 object-oriented, then you can invoke a script method on a script
sundar@68 291 object.</p>
sundar@68 292 <pre><code>
sundar@68 293 // <a href="source/InvokeScriptMethod.java">InvokeScriptMethod.java</a>
sundar@68 294
sundar@68 295 import javax.script.*;
sundar@68 296
sundar@68 297 public class InvokeScriptMethod {
sundar@68 298 public static void main(String[] args) throws Exception {
sundar@68 299 ScriptEngineManager manager = new ScriptEngineManager();
sundar@68 300 ScriptEngine engine = manager.getEngineByName("nashorn");
sundar@68 301
sundar@68 302 // JavaScript code in a String. This code defines a script object 'obj'
sundar@68 303 // with one method called 'hello'.
sundar@68 304 String script = "var obj = new Object(); obj.hello = function(name) { print('Hello, ' + name); }";
sundar@68 305 // evaluate script
sundar@68 306 engine.eval(script);
sundar@68 307
sundar@68 308 // <code>javax.script.Invocable</code> is an optional interface.
sundar@68 309 // Check whether your script engine implements or not!
sundar@68 310 // Note that the JavaScript engine implements Invocable interface.
sundar@68 311 <span class="classref">Invocable</span> inv = (Invocable) engine;
sundar@68 312
sundar@68 313 // get script object on which we want to call the method
sundar@68 314 Object obj = engine.<span class="methodref">get</span>("obj");
sundar@68 315
sundar@68 316 // invoke the method named "hello" on the script object "obj"
sundar@68 317 inv.<span class="methodref">invokeMethod</span>(obj, "hello", "Script Method !!" );
sundar@68 318 }
sundar@68 319 }
sundar@68 320
sundar@68 321 </code>
sundar@68 322 </pre>
sundar@68 323 <hr>
sundar@68 324 <a name="interfaces" id="interfaces"></a>
sundar@68 325 <h3>Implementing Java Interfaces by Scripts</h3>
sundar@68 326 <p>Instead of calling specific script functions from Java,
sundar@68 327 sometimes it is convenient to implement a Java interface by script
sundar@68 328 functions or methods. Also, by using interfaces we can avoid having
sundar@68 329 to use the <code>javax.script</code> API in many places. We can get
sundar@68 330 an interface implementor object and pass it to various Java APIs.
sundar@68 331 The following example demonstrates implementing the
sundar@68 332 <code>java.lang.Runnable</code> interface with a script.</p>
sundar@68 333 <pre><code>
sundar@68 334 // <a href="source/RunnableImpl.java">RunnableImpl.java</a>
sundar@68 335
sundar@68 336 import javax.script.*;
sundar@68 337
sundar@68 338 public class RunnableImpl {
sundar@68 339 public static void main(String[] args) throws Exception {
sundar@68 340 ScriptEngineManager manager = new ScriptEngineManager();
sundar@68 341 ScriptEngine engine = manager.getEngineByName("nashorn");
sundar@68 342
sundar@68 343 // JavaScript code in a String
sundar@68 344 String script = "function run() { print('run called'); }";
sundar@68 345
sundar@68 346 // evaluate script
sundar@68 347 engine.eval(script);
sundar@68 348
sundar@68 349 <span class="classref">Invocable</span> inv = (Invocable) engine;
sundar@68 350
sundar@68 351 // get Runnable interface object from engine. This interface methods
sundar@68 352 // are implemented by script functions with the matching name.
sundar@68 353 Runnable r = inv.<span class="methodref">getInterface</span>(Runnable.class);
sundar@68 354
sundar@68 355 // start a new thread that runs the script implemented
sundar@68 356 // runnable interface
sundar@68 357 Thread th = new Thread(r);
sundar@68 358 th.start();
sundar@68 359 th.join();
sundar@68 360 }
sundar@68 361 }
sundar@68 362 </code>
sundar@68 363 </pre>
sundar@68 364 <p>If your scripting language is object-based or object-oriented,
sundar@68 365 it is possible to implement a Java interface by script methods on
sundar@68 366 script objects. This avoids having to call script global functions
sundar@68 367 for interface methods. The script object can store the "state"
sundar@68 368 associated with the interface implementor.</p>
sundar@68 369 <pre><code>
sundar@68 370 // <a href="source/RunnableImplObject.java">RunnableImplObject.java</a>
sundar@68 371
sundar@68 372 import javax.script.*;
sundar@68 373
sundar@68 374 public class RunnableImplObject {
sundar@68 375 public static void main(String[] args) throws Exception {
sundar@68 376 ScriptEngineManager manager = new ScriptEngineManager();
sundar@68 377 ScriptEngine engine = manager.getEngineByName("nashorn");
sundar@68 378
sundar@68 379 // JavaScript code in a String
sundar@68 380 String script = "var obj = new Object(); obj.run = function() { print('run method called'); }";
sundar@68 381
sundar@68 382 // evaluate script
sundar@68 383 engine.eval(script);
sundar@68 384
sundar@68 385 // get script object on which we want to implement the interface with
sundar@68 386 Object obj = engine.<span class="methodref">get</span>("obj");
sundar@68 387
sundar@68 388 <span class="classref">Invocable</span> inv = (Invocable) engine;
sundar@68 389
sundar@68 390 // get Runnable interface object from engine. This interface methods
sundar@68 391 // are implemented by script methods of object 'obj'
sundar@68 392 Runnable r = inv.<span class="methodref">getInterface</span>(obj, Runnable.class);
sundar@68 393
sundar@68 394 // start a new thread that runs the script implemented
sundar@68 395 // runnable interface
sundar@68 396 Thread th = new Thread(r);
sundar@68 397 th.start();
sundar@68 398 th.join();
sundar@68 399 }
sundar@68 400 }
sundar@68 401 </code>
sundar@68 402 </pre>
sundar@68 403 <hr>
sundar@68 404 <a name="scopes" id="scopes"></a>
sundar@68 405 <h3>Multiple Scopes for Scripts</h3>
sundar@68 406 <p>In the <a href="#scriptvars">script variables</a> example, we
sundar@68 407 saw how to expose application objects as script global variables.
sundar@68 408 It is possible to expose multiple global "scopes" for scripts. A
sundar@68 409 single scope is an instance of <code>javax.script.Bindings</code>.
sundar@68 410 This interface is derived from <code>java.util.Map&lt;String,
sundar@68 411 Object&gt;</code>. A scope a set of name-value pairs where name is
sundar@68 412 any non-empty, non-null String.
sundar@68 413 <code>javax.script.ScriptContext</code> interface supports multiple
sundar@68 414 scopes with associated Bindings for each
sundar@68 415 scope. By default, every script engine has a default script
sundar@68 416 context. The default script context has atleast one scope called
sundar@68 417 "ENGINE_SCOPE". Various scopes supported by a script context are
sundar@68 418 available through <code>getScopes</code> method.</p>
sundar@68 419 <pre><code>
sundar@68 420 // <a href="source/MultiScopes.java">MultiScopes.java</a>
sundar@68 421
sundar@68 422 import javax.script.*;
sundar@68 423
sundar@68 424 public class MultiScopes {
sundar@68 425 public static void main(String[] args) throws Exception {
sundar@68 426 ScriptEngineManager manager = new ScriptEngineManager();
sundar@68 427 ScriptEngine engine = manager.getEngineByName("nashorn");
sundar@68 428
sundar@68 429 engine.put("x", "hello");
sundar@68 430 // print global variable "x"
sundar@68 431 engine.eval("print(x);");
sundar@68 432 // the above line prints "hello"
sundar@68 433
sundar@68 434 // Now, pass a different script context
sundar@68 435 <span class="classref">ScriptContext</span> newContext = new <span class="classref">SimpleScriptContext</span>();
sundar@68 436 newContext.setBindings(engine.createBindings(), ScriptContext.ENGINE_SCOPE);
sundar@68 437 <span class="classref">Bindings</span> engineScope = newContext.<span class="methodref">getBindings</span>(ScriptContext.ENGINE_SCOPE);
sundar@68 438
sundar@68 439 // add new variable "x" to the new engineScope
sundar@68 440 engineScope.<span class="methodref">put</span>("x", "world");
sundar@68 441
sundar@68 442 // execute the same script - but this time pass a different script context
sundar@68 443 engine.eval("print(x);", newContext);
sundar@68 444 // the above line prints "world"
sundar@68 445 }
sundar@68 446 }
sundar@68 447
sundar@68 448 </code>
sundar@68 449 </pre>
sundar@68 450 <hr>
sundar@68 451 <a name="jsengine" id="jsengine"></a>
sundar@68 452 <h2>JavaScript Script Engine</h2>
sundar@68 453 <p>Oracle's implementation of JDK 8 is co-bundled with the Nashorn ECMAScript
sundar@68 454 script engine.
sundar@68 455 <hr>
sundar@68 456 <a name="jstojava" id="jstojava"></a>
sundar@68 457 <h2>JavaScript to Java Communication</h2>
sundar@68 458 <p>For the most part, accessing Java classes, objects and methods
sundar@68 459 is straightforward. In particular field and method access from
sundar@68 460 JavaScript is the same as it is from Java. We highlight important
sundar@68 461 aspects of JavaScript Java access here.
sundar@68 462 The following examples are JavaScript snippets accessing Java. This
sundar@68 463 section requires knowledge of JavaScript. This section can be
sundar@68 464 skipped if you are planning to use some other JSR-223 scripting
sundar@68 465 language rather than JavaScript.</p>
sundar@68 466 <hr>
sundar@68 467 <a name="jsjavaclass" id=jsjavalass"></a>
sundar@68 468 <h3>Accessing Java Classes</h3>
sundar@68 469 <pre>
sundar@68 470 <code>
sundar@68 471 // <a href="source/javatypes.js">javatypes.js</a>
sundar@68 472
sundar@68 473 var arrayListType = Java.type("java.util.ArrayList")
sundar@68 474 var intType = Java.type("int")
sundar@68 475 var stringArrayType = Java.type("java.lang.String[]")
sundar@68 476 var int2DArrayType = Java.type("int[][]")
sundar@68 477 </code>
sundar@68 478 </pre>
sundar@68 479
attila@267 480 Note that the name of the type is always a string for a fully qualified name. You can use any of these expressions to create new instances, e.g.:
sundar@68 481
sundar@68 482 <pre><code>
attila@267 483 var anArrayList = new (Java.type("java.util.ArrayList"))
sundar@68 484 </code></pre>
sundar@68 485
sundar@68 486 or
sundar@68 487
sundar@68 488 <pre><code>
sundar@68 489 var ArrayList = Java.type("java.util.ArrayList")
sundar@68 490 var anArrayList = new ArrayList
sundar@68 491 var anArrayListWithSize = new ArrayList(16)
sundar@68 492 </code></pre>
sundar@68 493
sundar@68 494 In the special case of inner classes, you need to use the JVM fully qualified name, meaning using $ sign in the class name:
sundar@68 495
sundar@68 496 <pre><code>
sundar@68 497 var ftype = Java.type("java.awt.geom.Arc2D$Float")
sundar@68 498 </code></pre>
sundar@68 499
sundar@68 500
sundar@68 501 However, once you retrieved the outer class, you can access the inner class as a property on it:
sundar@68 502
sundar@68 503 <pre><code>
sundar@68 504 var arctype = Java.type("java.awt.geom.Arc2D")
sundar@68 505 var ftype = arctype.Float
sundar@68 506 </code></pre>
sundar@68 507 <p>
sundar@68 508 You can access both static and non-static inner classes. If you want to create an instance of a non-static inner class, remember to pass an instance of its outer class as the first argument to the constructor.
sundar@68 509 </p>
attila@267 510 <p>
attila@267 511 In addition to creating new instances, the type objects returned from <code>Java.type</code> calls can also be used to access the
attila@267 512 static fields and methods of the classes:
attila@267 513 <pre><code>
attila@267 514 var File = Java.type("java.io.File")
attila@267 515 File.createTempFile("nashorn", ".tmp")
attila@267 516 </code></pre>
attila@267 517 <p>
attila@267 518 Methods with names of the form <code>isXxx()</code>, <code>getXxx()</code>, and <code>setXxx()</code> can also be used as properties, for both instances and statics.
attila@267 519 </p>
attila@267 520 <p>
attila@267 521 A type object returned from <code>Java.type</code> is distinct from a <code>java.lang.Class</code> object. You can obtain one from the other using properties <code>class</code> and <code>static</code> on them.
attila@267 522 <pre><code>
attila@267 523 var ArrayList = Java.type("java.util.ArrayList")
attila@267 524 var a = new ArrayList
attila@267 525
attila@267 526 // All of the following print true:
attila@267 527 print("Type acts as target of instanceof: " + (a instanceof ArrayList))
attila@267 528 print("Class doesn't act as target of instanceof: " + !(a instanceof a.getClass()))
attila@267 529 print("Type is not same as instance's getClass(): " + (a.getClass() !== ArrayList))
attila@267 530 print("Type's `class` property is same as instance getClass(): " + (a.getClass() === ArrayList.class))
attila@267 531 print("Type is same as instance getClass()'s `static` property: " + (a.getClass().static === ArrayList))
attila@267 532 </code></pre>
attila@267 533 <p>
attila@267 534 You can think of the type object as similar to the class names as used in Java source code: you use them as the
attila@267 535 arguments to the <code>new</code> and <code>instanceof</code> operators and as the namespace for the static fields
attila@267 536 and methods, but they are different than the runtime <code>Class</code> objects returned by <code>getClass()</code> calls.
attila@267 537 Syntactically and semantically, this separation produces code that is most similar to Java code, where a distinction
attila@267 538 between compile-time class expressions and runtime class objects also exists. (Also, Java can't have the equivalent of <code>static</code>
attila@267 539 property on a <code>Class</code> object since compile-time class expressions are never reified as objects).
attila@267 540 </p>
sundar@68 541 <hr>
sundar@68 542 <a name="jsimport" id="jsimport"></a>
sundar@68 543 <h3>Importing Java Packages, Classes</h3>
sundar@68 544 <p>The built-in functions <code>importPackage</code> (in compatibility script) and
sundar@68 545 <code>importClass</code> can be used to import Java packages and
sundar@68 546 classes.</p>
sundar@68 547 <pre><code>
sundar@68 548
sundar@68 549 // <a href="source/importpackageclass.js">importpackageclass.js</a>
sundar@68 550
sundar@68 551 // load compatibility script
sundar@68 552 load("nashorn:mozilla_compat.js");
sundar@68 553 // Import Java packages and classes
sundar@68 554 // like import package.*; in Java
sundar@68 555 <span class="functionref">importPackage</span>(java.awt);
sundar@68 556 // like import java.awt.Frame in Java
sundar@68 557 <span class="functionref">importClass</span>(java.awt.Frame);
sundar@68 558 // Create Java Objects by "new ClassName"
sundar@68 559 var frame = new java.awt.Frame("hello");
sundar@68 560 // Call Java public methods from script
sundar@68 561 frame.setVisible(true);
sundar@68 562 // Access "JavaBean" properties like "fields"
sundar@68 563 print(frame.title);
sundar@68 564 </code>
sundar@68 565 </pre>
sundar@68 566 <p>The <span class="objectref">Packages</span> global variable can
sundar@68 567 be used to access Java packages. Examples:
sundar@68 568 <code>Packages.java.util.Vector</code>,
sundar@68 569 <code>Packages.javax.swing.JFrame</code>. Please note that "java"
sundar@68 570 is a shortcut for "Packages.java". There are equivalent shortcuts
sundar@68 571 for javax, org, edu, com, net prefixes, so pratically all JDK
sundar@68 572 platform classes can be accessed without the "Packages" prefix.</p>
sundar@68 573 <p>Note that java.lang is not imported by default (unlike Java)
sundar@68 574 because that would result in conflicts with JavaScript's built-in
sundar@68 575 Object, Boolean, Math and so on.</p>
sundar@68 576 <p><code>importPackage</code> and <code>importClass</code>
sundar@68 577 functions "pollute" the global variable scope of JavaScript. To
sundar@68 578 avoid that, you may use <span class="functionref">JavaImporter</span>.</p>
sundar@68 579 <pre><code>
sundar@68 580
sundar@68 581 // <a href="source/javaimporter.js">javaimporter.js</a>
sundar@68 582
sundar@68 583 // create JavaImporter with specific packages and classes to import
sundar@68 584
sundar@68 585 var SwingGui = new <span class="functionref">JavaImporter</span>(javax.swing,
sundar@68 586 javax.swing.event,
sundar@68 587 javax.swing.border,
sundar@68 588 java.awt.event);
sundar@68 589 with (SwingGui) {
sundar@68 590 // within this 'with' statement, we can access Swing and AWT
sundar@68 591 // classes by unqualified (simple) names.
sundar@68 592
sundar@68 593 var mybutton = new JButton("test");
sundar@68 594 var myframe = new JFrame("test");
sundar@68 595 }
sundar@68 596
sundar@68 597 </code>
sundar@68 598 </pre>
sundar@68 599 <hr>
sundar@68 600 <a name="jsarrays" id="jsarrays"></a>
sundar@68 601 <h3>Creating, Converting and Using Java Arrays</h3>
sundar@136 602 <p>
attila@267 603 Array element access or length access is the same as in Java.</p>
sundar@68 604 <pre><code>
sundar@68 605 // <a href="source/javaarray.js">javaarray.js</a>
sundar@68 606
sundar@68 607 // create Java String array of 5 elements
sundar@136 608 var StringArray = Java.type("java.lang.String[]");
sundar@136 609 var a = new StringArray(5);
sundar@68 610
sundar@68 611 // Accessing elements and length access is by usual Java syntax
sundar@68 612 a[0] = "scripting is great!";
sundar@68 613 print(a.length);
sundar@68 614 print(a[0]);
sundar@68 615 </code>
sundar@68 616 </pre>
sundar@68 617 <p>
sundar@68 618 It is also possible to convert between JavaScript and Java arrays.
sundar@68 619 Given a JavaScript array and a Java type, <code>Java.toJavaArray</code> returns a Java array with the same initial contents, and with the specified component type.
sundar@68 620 </p>
sundar@68 621 <pre><code>
sundar@68 622 var anArray = [1, "13", false]
sundar@68 623 var javaIntArray = Java.toJavaArray(anArray, "int")
sundar@68 624 print(javaIntArray[0]) // prints 1
sundar@68 625 print(javaIntArray[1]) // prints 13, as string "13" was converted to number 13 as per ECMAScript ToNumber conversion
sundar@68 626 print(javaIntArray[2]) // prints 0, as boolean false was converted to number 0 as per ECMAScript ToNumber conversion
sundar@68 627 </code></pre>
sundar@68 628 <p>
attila@267 629 You can use either a string or a type object returned from <code>Java.type()</code> to specify the component type of the array.
attila@267 630 You can also omit the array type, in which case a <code>Object[]</code> will be created.
attila@267 631 </p>
attila@267 632 <p>
attila@267 633 Given a Java array or Collection, <code>Java.toJavaScriptArray</code> returns a JavaScript array with a shallow copy of its contents. Note that in most cases, you can use Java arrays and lists natively in Nashorn; in cases where for some reason you need to have an actual JavaScript native array (e.g. to work with the array comprehensions functions), you will want to use this method.
sundar@68 634 </p>
sundar@68 635 <pre><code>
sundar@68 636 var File = Java.type("java.io.File");
sundar@68 637 var listCurDir = new File(".").listFiles();
sundar@68 638 var jsList = Java.toJavaScriptArray(listCurDir);
sundar@68 639 print(jsList);
sundar@68 640 </code></pre>
sundar@68 641 <hr>
sundar@68 642 <a name="jsimplement" id="jsimplement"></a>
attila@267 643 <h3>Implementing Java interfaces</h3>
sundar@68 644 <p>A Java interface can be implemented in JavaScript by using a
sundar@68 645 Java anonymous class-like syntax:</p>
sundar@68 646 <pre><code>
sundar@68 647 // <a href="source/runnable.js">runnable.js</a>
sundar@68 648
sundar@68 649 var r = new java.lang.Runnable() {
sundar@68 650 run: function() {
sundar@68 651 print("running...\n");
sundar@68 652 }
sundar@68 653 };
sundar@68 654
sundar@68 655 // "r" can be passed to Java methods that expect java.lang.Runnable
sundar@68 656 var th = new java.lang.Thread(r);
sundar@68 657 th.start();
sundar@68 658 th.join();
sundar@68 659 </code>
sundar@68 660 </pre>
sundar@68 661 <p>When an interface with a single method is expected, you can pass
sundar@68 662 a script function directly.(auto conversion)</p>
sundar@68 663 <pre><code>
sundar@68 664 // <a href="source/samfunc.js">samfunc.js</a>
sundar@68 665
sundar@68 666 function func() {
sundar@68 667 print("I am func!");
sundar@68 668 }
sundar@68 669
sundar@68 670 // pass script function for java.lang.Runnable argument
sundar@68 671 var th = new java.lang.Thread(func);
sundar@68 672 th.start();
sundar@68 673 th.join();
sundar@68 674 </code>
sundar@68 675 </pre>
sundar@68 676 <hr>
attila@267 677 <a name="jsextendabstract" id="jsextendabstract"></a>
attila@267 678 <h3>Extending Abstract Java Classes</h3>
sundar@68 679 <p>
sundar@68 680 If a Java class is abstract, you can instantiate an anonymous subclass of it using an argument list that is applicable to any of its public or protected constructors, but inserting a JavaScript object with functions properties that provide JavaScript implementations of the abstract methods. If method names are overloaded, the JavaScript function will provide implementation for all overloads. E.g.:
sundar@68 681 </p>
sundar@68 682
sundar@68 683 <pre><code>
sundar@68 684 var TimerTask = Java.type("java.util.TimerTask")
sundar@68 685 var task = new TimerTask({ run: function() { print("Hello World!") } })
sundar@68 686 </code></pre>
sundar@68 687
sundar@68 688 Nashorn supports a syntactic extension where a "new" expression followed by an argument is identical to invoking the constructor and passing the argument to it, so you can write the above example also as:
sundar@68 689
sundar@68 690 <pre><code>
sundar@68 691 var task = new TimerTask {
sundar@68 692 run: function() {
sundar@68 693 print("Hello World!")
sundar@68 694 }
sundar@68 695 }
sundar@68 696 </code></pre>
sundar@68 697
sundar@68 698 which is very similar to Java anonymous inner class definition. On the other hand, if the type is an abstract type with a single abstract method (commonly referred to as a "SAM type") or all abstract methods it has share the same overloaded name), then instead of an object, you can just pass a function, so the above example can become even more simplified to:
sundar@68 699
sundar@68 700 <pre><code>
sundar@68 701 var task = new TimerTask(function() { print("Hello World!") })
sundar@68 702 </code></pre>
sundar@68 703
sundar@68 704 <p>
sundar@68 705 Note that in every one of these cases if you are trying to instantiate an abstract class that has constructors that take some arguments, you can invoke those simply by specifying the arguments after the initial implementation object or function.
sundar@68 706 </p>
sundar@68 707 <p>
sundar@68 708 The use of functions can be taken even further; if you are invoking a Java method that takes a SAM type, you can just pass in a function object, and Nashorn will know what you meant:
sundar@68 709 </p>
sundar@68 710 <code><pre>
sundar@68 711 Java.type("java.util.Timer")
sundar@68 712 timer.schedule(function() { print("Hello World!") })
sundar@68 713 </code></pre>
sundar@68 714
sundar@68 715 Here, <code>Timer.schedule()</code> expects a <code>TimerTask</code> as its argument, so Nashorn creates an instance of a TimerTask subclass and uses the passed function to implement its only abstract method, run(). In this usage though, you can't use non-default constructors; the type must be either an interface, or must have a protected or public no-arg constructor.
sundar@68 716
attila@267 717 <hr>
attila@267 718 <a name="jsextendconcrete" id="jsextendconcrete"></a>
attila@267 719 <h3>Extending Concrete Java Classes</h3>
sundar@68 720 <p>
sundar@68 721 To extend a concrete Java class, you have to use <code>Java.extend</code> function.
sundar@68 722 <code>Java.extend</code> returns a type object for a subclass of the specified Java class (or implementation of the specified interface) that acts as a script-to-Java adapter for it.
sundar@68 723 </p>
sundar@68 724 <pre><code>
sundar@68 725 // <a href="source/javaextend.js">javaextend.js</a>
sundar@68 726
sundar@68 727 var ArrayList = Java.type("java.util.ArrayList")
sundar@68 728 var ArrayListExtender = Java.extend(ArrayList)
sundar@68 729 var printSizeInvokedArrayList = new ArrayListExtender() {
sundar@68 730 size: function() { print("size invoked!"); }
sundar@68 731 }
sundar@68 732 var printAddInvokedArrayList = new ArrayListExtender() {
sundar@68 733 add: function(x, y) {
sundar@68 734 if(typeof(y) === "undefined") {
sundar@68 735 print("add(e) invoked!");
sundar@68 736 } else {
sundar@68 737 print("add(i, e) invoked!");
sundar@68 738 }
sundar@68 739 }
sundar@68 740 };
sundar@68 741 printSizeInvokedArrayList.size();
sundar@68 742 printAddInvokedArrayList.add(33, 33);
sundar@68 743 </code></pre>
attila@267 744 <p>
attila@267 745 The reason you must use <code>Java.extend()</code> with concrete classes is that with concrete classes, there can be a
attila@267 746 syntactic ambiguity if you just invoke their constructor. Consider this example:
attila@267 747 </p>
attila@267 748 <pre><code>
attila@267 749 var t = new java.lang.Thread({ run: function() { print("Hello!") } })
attila@267 750 </code></pre>
attila@267 751 <p>
attila@267 752 If we allowed subclassing of concrete classes with constructor syntax, Nashorn couldn't tell if you're creating a new
attila@267 753 <code>Thread</code> and passing it a <code>Runnable</code> at this point, or you are subclassing <code>Thread</code> and
attila@267 754 passing it a new implementation for its own <code>run()</code> method.
attila@267 755 </p>
attila@267 756 <hr>
attila@267 757 <a name="jsimplementmultiple" id="jsimplementmultiple"></a>
attila@267 758 <h3>Implementing Multiple Interfaces</h3>
attila@267 759 <p>
attila@267 760 <code>Java.extend</code> can in fact take a list of multiple types. At most one of the types can be a class, and the rest must
attila@267 761 be interfaces (the class doesn't have to be the first in the list). You will get back an object that extends the class and
attila@267 762 implements all the interfaces. (Obviously, if you only specify interfaces and no class, the object will extend <code>java.lang.Object</code>).
attila@267 763 <hr>
attila@267 764 <a name="classBoundImplementations" id="classBoundImplementations"></a>
attila@267 765 <h3>Class-Bound Implementations</h3>
attila@267 766 <p>
attila@267 767 The methods shown so far for extending Java classes and implementing interfaces &ndash; passing an implementation JavaScript object
attila@267 768 or function to a constructor, or using <code>Java.extend</code> with <code>new</code> &ndash; all produce classes that take an
attila@267 769 extra JavaScript object parameter in their constructors that specifies the implementation. The implementation is therefore always bound
attila@267 770 to the actual instance being created with <code>new</code>, and not to the whole class. This has some advantages, for example in the
attila@267 771 memory footprint of the runtime, as Nashorn can just create a single "universal adapter" for every combination of types being implemented.
attila@267 772 In reality, the below code shows that different instantiations of, say, <code>Runnable</code> have the same class regardless of them having
attila@267 773 different JavaScript implementation objects:
attila@267 774 </p>
attila@267 775 <pre><code>
attila@267 776 var Runnable = java.lang.Runnable;
attila@267 777 var r1 = new Runnable(function() { print("I'm runnable 1!") })
attila@267 778 var r2 = new Runnable(function() { print("I'm runnable 2!") })
attila@267 779 r1.run()
attila@267 780 r2.run()
attila@267 781 print("We share the same class: " + (r1.class === r2.class))
attila@267 782 </code></pre>
attila@267 783 <p>
attila@267 784 prints:
attila@267 785 </p>
attila@267 786 <pre><code>
attila@267 787 I'm runnable 1!
attila@267 788 I'm runnable 2!
attila@267 789 We share the same class: true
attila@267 790 </code></pre>
attila@267 791 <p>
attila@267 792 Sometimes, however, you'll want to extend a Java class or implement an interface with implementation bound to the class, not to
attila@267 793 its instances. Such a need arises, for example, when you need to pass the class for instantiation to an external API; prime example
attila@267 794 of this is the JavaFX framework where you need to pass an Application class to the FX API and let it instantiate it.
attila@267 795 </p>
attila@267 796 <p>
attila@267 797 Fortunately, there's a solution for that: <code>Java.extend()</code> &ndash; aside from being able to take any number of type parameters
attila@267 798 denoting a class to extend and interfaces to implement &ndash; can also take one last argument that has to be a JavaScript object
attila@267 799 that serves as the implementation for the methods. In this case, <code>Java.extend()</code> will create a class that has the same
attila@267 800 constructors as the original class had, as they don't need to take an an extra implementation object parameter. The example below
attila@267 801 shows how you can create class-bound implementations, and shows that in this case, the implementation classes for different invocations
attila@267 802 are indeed different:
attila@267 803 </p>
attila@267 804 <pre><code>
attila@267 805 var RunnableImpl1 = Java.extend(java.lang.Runnable, function() { print("I'm runnable 1!") })
attila@267 806 var RunnableImpl2 = Java.extend(java.lang.Runnable, function() { print("I'm runnable 2!") })
attila@267 807 var r1 = new RunnableImpl1()
attila@267 808 var r2 = new RunnableImpl2()
attila@267 809 r1.run()
attila@267 810 r2.run()
attila@267 811 print("We share the same class: " + (r1.class === r2.class))
attila@267 812 </code></pre>
attila@267 813 <p>
attila@267 814 prints:
attila@267 815 </p>
attila@267 816 <pre><code>
attila@267 817 I'm runnable 1!
attila@267 818 I'm runnable 2!
attila@267 819 We share the same class: false
attila@267 820 </code></pre>
attila@267 821 <p>
attila@267 822 As you can see, the major difference here is that we moved the implementation object into the invocation of <code>Java.extend</code>
attila@267 823 from the constructor invocations &ndash; indeed the constructor invocations now don't even need to take an extra parameter! Since
attila@267 824 the implementations are bound to a class, the two classes obviously can't be the same, and we indeed see that the two runnables no
attila@267 825 longer share the same class &ndash; every invocation of <code>Java.extend()</code> with a class-specific implementation object triggers
attila@267 826 the creation of a new Java adapter class.
attila@267 827 </p>
attila@267 828 <p>
attila@267 829 Finally, the adapter classes with class-bound implementations can <i>still</i> take an additional constructor parameter to further
attila@267 830 override the behavior on a per-instance basis. Thus, you can even combine the two approaches: you can provide part of the implementation
attila@267 831 in a class-based JavaScript implementation object passed to <code>Java.extend</code>, and part in another object passed to the constructor.
attila@267 832 Whatever functions are provided by the constructor-passed object will override the functions in the class-bound object.
attila@267 833 </p>
attila@267 834 <pre><code>
attila@267 835 var RunnableImpl = Java.extend(java.lang.Runnable, function() { print("I'm runnable 1!") })
attila@267 836 var r1 = new RunnableImpl()
attila@267 837 var r2 = new RunnableImpl(function() { print("I'm runnable 2!") })
attila@267 838 r1.run()
attila@267 839 r2.run()
attila@267 840 print("We share the same class: " + (r1.class === r2.class))
attila@267 841 </code></pre>
attila@267 842 <p>
attila@267 843 prints:
attila@267 844 </p>
attila@267 845 <pre><code>
attila@267 846 I'm runnable 1!
attila@267 847 I'm runnable 2!
attila@267 848 We share the same class: true
attila@267 849 </code></pre>
sundar@68 850 <hr>
sundar@68 851 <a name="jsoverload" id="jsoverload"></a>
sundar@68 852 <h3>Overload Resolution</h3>
sundar@68 853 <p>Java methods can be overloaded by argument types. In Java,
sundar@68 854 overload resolution occurs at compile time (performed by javac).
attila@267 855 When calling Java methods from Nashorn, the appropriate method will be
attila@267 856 selected based on the argument types at invocation time. You do not need
attila@267 857 to do anything special &ndash; the correct Java method overload variant
attila@267 858 is selected based automatically. You still have the option of explicitly
attila@267 859 specifying a particular overload variant. Reasons for this include
attila@267 860 either running into a genuine ambiguity with actual argument types, or
attila@267 861 rarely reasons of performance &ndash; if you specify the actual overload
attila@267 862 then the engine doesn't have to perform resolution during invocation.
attila@267 863 Individual overloads of a Java methods are exposed as special properties
attila@267 864 with the name of the method followed with its signature in parentheses.
attila@267 865 You can invoke them like this:</p>
sundar@68 866 <pre><code>
sundar@68 867 // <a href="source/overload.js">overload.js</a>
sundar@68 868
sundar@68 869 var out = java.lang.System.out;
sundar@68 870
sundar@68 871 // select a particular print function
attila@267 872 out["println(Object)"]("hello");
sundar@68 873 </code>
sundar@68 874 </pre>
attila@267 875 <p>
attila@267 876 Note that you normally don't even have to use qualified class names in
attila@267 877 the signatures as long as the unqualified name of the type is sufficient
attila@267 878 for uniquely identifying the signature. In practice this means that only
attila@267 879 in the extremely unlikely case that two overloads only differ in
attila@267 880 parameter types that have identical unqualified names but come from
attila@267 881 different packages would you need to use the fully qualified name of the
attila@267 882 class.
attila@267 883 </p>
attila@267 884 <hr>
attila@267 885 <a name="dataTypeMapping" id="dataTypeMapping"></a>
attila@267 886 <h3>Mapping of Data Types Between Java and JavaScript</h3>
attila@267 887 <p>
attila@267 888 We have previously shown some of the data type mappings between Java and JavaScript.
attila@267 889 We saw that arrays need to be explicitly converted. We have also shown that JavaScript functions
attila@267 890 are automatically converted to SAM types when passed as parameters to Java methods. Most other
attila@267 891 conversions work as you would expect.
attila@267 892 </p>
attila@267 893 <p>
attila@267 894 Every JavaScript object is also a <code>java.util.Map</code> so APIs receiving maps will receive them directly.
attila@267 895 </p>
attila@267 896 <p>
attila@267 897 When numbers are passed to a Java API, they will be converted to the expected target numeric type, either boxed or
attila@267 898 primitive, but if the target type is less specific, say <code>Number</code> or <code>Object</code>, you can only
attila@267 899 count on them being a <code>Number</code>, and have to test specifically for whether it's a boxed <code>Double</code>,
attila@267 900 <code>Integer</code>, <code>Long</code>, etc. &ndash; it can be any of these due to internal optimizations. Also, you
attila@267 901 can pass any JavaScript value to a Java API expecting either a boxed or primitive number; the JavaScript specification's
attila@267 902 <code>ToNumber</code> conversion algorithm will be applied to the value.
attila@267 903 </p>
attila@267 904 <p>
attila@267 905 In a similar vein, if a Java method expects a <code>String</code> or a <code>Boolean</code>, the values will be
attila@267 906 converted using all conversions allowed by the JavaScript specification's <code>ToString</code> and <code>ToBoolean</code>
attila@267 907 conversions.
attila@267 908 </p>
attila@267 909 <p>
attila@267 910 Finally, a word of caution about strings. Due to internal performance optimizations of string operations, JavaScript strings are
attila@267 911 not always necessarily of type <code>java.lang.String</code>, but they will always be of type <code>java.lang.CharSequence</code>.
attila@267 912 If you pass them to a Java method that expects a <code>java.lang.String</code> parameter, then you will naturally receive a Java
attila@267 913 String, but if the signature of your method is more generic, i.e. it receives a <code>java.lang.Object</code> parameter, you can
attila@267 914 end up with an object of private engine implementation class that implements <code>CharSequence</code> but is not a Java String.
attila@267 915 </p>
sundar@68 916 <hr>
sundar@68 917 <a name="engineimpl" id="engineimpl"></a>
sundar@68 918 <h2>Implementing Your Own Script Engine</h2>
sundar@68 919 <p>We will not cover implementation of JSR-223 compliant script
sundar@68 920 engines in detail. Minimally, you need to implement the
sundar@68 921 <code>javax.script.ScriptEngine</code> and
sundar@68 922 <code>javax.script.ScriptEngineFactory</code> interfaces. The
sundar@68 923 abstract class <code>javax.script.AbstractScriptEngine</code>
sundar@68 924 provides useful defaults for a few methods of the
sundar@68 925 <code>ScriptEngine</code> interface.</p>
sundar@68 926 <p>Before starting to implement a JSR-223 engine, you may want to
sundar@68 927 check <a href="http://java.net/projects/Scripting">http://java.net/projects/Scripting</a>
sundar@68 928 project. This project maintains JSR-223 implementations for many
sundar@68 929 popular open source scripting languages.</p>
sundar@68 930 <hr>
sundar@68 931 <a name="refs" id="refs"></a>
sundar@68 932 <h2>References</h2>
sundar@68 933 <ul>
sundar@68 934 <li><a href="http://jcp.org/en/jsr/detail?id=223">JSR-223 Scripting
sundar@68 935 for the Java Platform</a></li>
sundar@68 936 <li><a href="http://java.net/projects/Scripting">http://java.net/projects/Scripting
sundar@68 937 </a></li>
sundar@68 938 </ul>
sundar@68 939
sundar@68 940
sundar@68 941
sundar@68 942 <div class="hr"><hr></div>
sundar@68 943 <table summary="layout" border="0" width="100%">
sundar@68 944 <tbody><tr valign="TOP">
sundar@68 945 <td width="30%"> <img src="Java%20Scripting%20Programmer%27s%20Guide_files/logo_oracle_footer.gif" alt="Oracle and/or its affiliates" border="0" height="29" width="100"><br>
sundar@68 946 <font size="+1"> <i>Java Technology</i></font> </td>
sundar@68 947
sundar@68 948 <td width="30%">
sundar@68 949 <p><font size="-2">
sundar@68 950 <a href="http://docs.oracle.com/javase/6/docs/legal/cpyr.html">Copyright ©</a> 2013, Oracle and/or its affiliates. All rights reserved.
sundar@68 951 </font></p>
sundar@68 952 </td>
sundar@68 953 <td width="30%">
sundar@68 954 <p align="right"><font size="-2"><a href="http://download.oracle.com/javase/feedback.html">Contact Us</a></font></p><font size="-2">
sundar@68 955 </font></td>
sundar@68 956 </tr>
sundar@68 957 </tbody></table>
sundar@68 958 <div class="hr"><hr></div>
sundar@68 959 </div>
sundar@68 960
sundar@68 961 <!-- Start SiteCatalyst code -->
sundar@68 962 <script language="JavaScript" src="Java%20Scripting%20Programmer%27s%20Guide_files/s_code_download.js"></script>
sundar@68 963 <script language="JavaScript" src="Java%20Scripting%20Programmer%27s%20Guide_files/s_code.js"></script>
sundar@68 964
sundar@68 965 <!-- ********** DO NOT ALTER ANYTHING BELOW THIS LINE ! *********** -->
sundar@68 966 <!-- Below code will send the info to Omniture server -->
sundar@68 967 <script language="javascript">var s_code=s.t();if(s_code)document.write(s_code)</script>
sundar@68 968
sundar@68 969 <!-- End SiteCatalyst code -->
sundar@68 970
sundar@68 971
sundar@68 972
sundar@68 973 </body></html>

mercurial