493 var arctype = Java.type("java.awt.geom.Arc2D") |
514 var arctype = Java.type("java.awt.geom.Arc2D") |
494 var ftype = arctype.Float |
515 var ftype = arctype.Float |
495 </code></pre> |
516 </code></pre> |
496 <p> |
517 <p> |
497 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. |
518 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. |
|
519 </p> |
|
520 <p> |
|
521 In addition to creating new instances, the type objects returned from <code>Java.type</code> calls can also be used to access the |
|
522 static fields and methods of the classes: |
|
523 <pre><code> |
|
524 var File = Java.type("java.io.File") |
|
525 File.createTempFile("nashorn", ".tmp") |
|
526 </code></pre> |
|
527 <p> |
|
528 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. |
|
529 </p> |
|
530 <p> |
|
531 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. |
|
532 <pre><code> |
|
533 var ArrayList = Java.type("java.util.ArrayList") |
|
534 var a = new ArrayList |
|
535 |
|
536 // All of the following print true: |
|
537 print("Type acts as target of instanceof: " + (a instanceof ArrayList)) |
|
538 print("Class doesn't act as target of instanceof: " + !(a instanceof a.getClass())) |
|
539 print("Type is not same as instance's getClass(): " + (a.getClass() !== ArrayList)) |
|
540 print("Type's `class` property is same as instance getClass(): " + (a.getClass() === ArrayList.class)) |
|
541 print("Type is same as instance getClass()'s `static` property: " + (a.getClass().static === ArrayList)) |
|
542 </code></pre> |
|
543 <p> |
|
544 You can think of the type object as similar to the class names as used in Java source code: you use them as the |
|
545 arguments to the <code>new</code> and <code>instanceof</code> operators and as the namespace for the static fields |
|
546 and methods, but they are different than the runtime <code>Class</code> objects returned by <code>getClass()</code> calls. |
|
547 Syntactically and semantically, this separation produces code that is most similar to Java code, where a distinction |
|
548 between compile-time class expressions and runtime class objects also exists. (Also, Java can't have the equivalent of <code>static</code> |
|
549 property on a <code>Class</code> object since compile-time class expressions are never reified as objects). |
498 </p> |
550 </p> |
499 <hr> |
551 <hr> |
500 <a name="jsimport" id="jsimport"></a> |
552 <a name="jsimport" id="jsimport"></a> |
501 <h3>Importing Java Packages, Classes</h3> |
553 <h3>Importing Java Packages, Classes</h3> |
502 <p>The built-in functions <code>importPackage</code> (in compatibility script) and |
554 <p>The built-in functions <code>importPackage</code> (in compatibility script) and |
575 print(a[0]); |
624 print(a[0]); |
576 </code> |
625 </code> |
577 </pre> |
626 </pre> |
578 <p> |
627 <p> |
579 It is also possible to convert between JavaScript and Java arrays. |
628 It is also possible to convert between JavaScript and Java arrays. |
580 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. |
629 Given a JavaScript array and a Java type, <code>Java.to</code> returns a Java array with the same initial contents, and with the specified array type. |
581 </p> |
630 </p> |
582 <pre><code> |
631 <pre><code> |
583 var anArray = [1, "13", false] |
632 var anArray = [1, "13", false] |
584 var javaIntArray = Java.toJavaArray(anArray, "int") |
633 var javaIntArray = Java.to(anArray, "int[]") |
585 print(javaIntArray[0]) // prints 1 |
634 print(javaIntArray[0]) // prints 1 |
586 print(javaIntArray[1]) // prints 13, as string "13" was converted to number 13 as per ECMAScript ToNumber conversion |
635 print(javaIntArray[1]) // prints 13, as string "13" was converted to number 13 as per ECMAScript ToNumber conversion |
587 print(javaIntArray[2]) // prints 0, as boolean false was converted to number 0 as per ECMAScript ToNumber conversion |
636 print(javaIntArray[2]) // prints 0, as boolean false was converted to number 0 as per ECMAScript ToNumber conversion |
588 </code></pre> |
637 </code></pre> |
589 <p> |
638 <p> |
590 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.i |
639 You can use either a string or a type object returned from <code>Java.type()</code> to specify the type of the array. |
|
640 You can also omit the array type, in which case a <code>Object[]</code> will be created. |
|
641 </p> |
|
642 <p> |
|
643 Given a Java array or Collection, <code>Java.from</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. |
591 </p> |
644 </p> |
592 <pre><code> |
645 <pre><code> |
593 var File = Java.type("java.io.File"); |
646 var File = Java.type("java.io.File"); |
594 var listCurDir = new File(".").listFiles(); |
647 var listCurDir = new File(".").listFiles(); |
595 var jsList = Java.toJavaScriptArray(listCurDir); |
648 var jsList = Java.from(listCurDir); |
596 print(jsList); |
649 print(jsList); |
597 </code></pre> |
650 </code></pre> |
598 <hr> |
651 <hr> |
599 <a name="jsimplement" id="jsimplement"></a> |
652 <a name="jsimplement" id="jsimplement"></a> |
600 <h3>Implementing Java Interfaces</h3> |
653 <h3>Implementing Java interfaces</h3> |
601 <p>A Java interface can be implemented in JavaScript by using a |
654 <p>A Java interface can be implemented in JavaScript by using a |
602 Java anonymous class-like syntax:</p> |
655 Java anonymous class-like syntax:</p> |
603 <pre><code> |
656 <pre><code> |
604 // <a href="source/runnable.js">runnable.js</a> |
657 // <a href="source/runnable.js">runnable.js</a> |
605 |
658 |
693 } |
749 } |
694 }; |
750 }; |
695 printSizeInvokedArrayList.size(); |
751 printSizeInvokedArrayList.size(); |
696 printAddInvokedArrayList.add(33, 33); |
752 printAddInvokedArrayList.add(33, 33); |
697 </code></pre> |
753 </code></pre> |
|
754 <p> |
|
755 The reason you must use <code>Java.extend()</code> with concrete classes is that with concrete classes, there can be a |
|
756 syntactic ambiguity if you just invoke their constructor. Consider this example: |
|
757 </p> |
|
758 <pre><code> |
|
759 var t = new java.lang.Thread({ run: function() { print("Hello!") } }) |
|
760 </code></pre> |
|
761 <p> |
|
762 If we allowed subclassing of concrete classes with constructor syntax, Nashorn couldn't tell if you're creating a new |
|
763 <code>Thread</code> and passing it a <code>Runnable</code> at this point, or you are subclassing <code>Thread</code> and |
|
764 passing it a new implementation for its own <code>run()</code> method. |
|
765 </p> |
|
766 <hr> |
|
767 <a name="jsimplementmultiple" id="jsimplementmultiple"></a> |
|
768 <h3>Implementing Multiple Interfaces</h3> |
|
769 <p> |
|
770 <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 |
|
771 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 |
|
772 implements all the interfaces. (Obviously, if you only specify interfaces and no class, the object will extend <code>java.lang.Object</code>). |
|
773 <hr> |
|
774 <a name="classBoundImplementations" id="classBoundImplementations"></a> |
|
775 <h3>Class-Bound Implementations</h3> |
|
776 <p> |
|
777 The methods shown so far for extending Java classes and implementing interfaces – passing an implementation JavaScript object |
|
778 or function to a constructor, or using <code>Java.extend</code> with <code>new</code> – all produce classes that take an |
|
779 extra JavaScript object parameter in their constructors that specifies the implementation. The implementation is therefore always bound |
|
780 to the actual instance being created with <code>new</code>, and not to the whole class. This has some advantages, for example in the |
|
781 memory footprint of the runtime, as Nashorn can just create a single "universal adapter" for every combination of types being implemented. |
|
782 In reality, the below code shows that different instantiations of, say, <code>Runnable</code> have the same class regardless of them having |
|
783 different JavaScript implementation objects: |
|
784 </p> |
|
785 <pre><code> |
|
786 var Runnable = java.lang.Runnable; |
|
787 var r1 = new Runnable(function() { print("I'm runnable 1!") }) |
|
788 var r2 = new Runnable(function() { print("I'm runnable 2!") }) |
|
789 r1.run() |
|
790 r2.run() |
|
791 print("We share the same class: " + (r1.class === r2.class)) |
|
792 </code></pre> |
|
793 <p> |
|
794 prints: |
|
795 </p> |
|
796 <pre><code> |
|
797 I'm runnable 1! |
|
798 I'm runnable 2! |
|
799 We share the same class: true |
|
800 </code></pre> |
|
801 <p> |
|
802 Sometimes, however, you'll want to extend a Java class or implement an interface with implementation bound to the class, not to |
|
803 its instances. Such a need arises, for example, when you need to pass the class for instantiation to an external API; prime example |
|
804 of this is the JavaFX framework where you need to pass an Application class to the FX API and let it instantiate it. |
|
805 </p> |
|
806 <p> |
|
807 Fortunately, there's a solution for that: <code>Java.extend()</code> – aside from being able to take any number of type parameters |
|
808 denoting a class to extend and interfaces to implement – can also take one last argument that has to be a JavaScript object |
|
809 that serves as the implementation for the methods. In this case, <code>Java.extend()</code> will create a class that has the same |
|
810 constructors as the original class had, as they don't need to take an an extra implementation object parameter. The example below |
|
811 shows how you can create class-bound implementations, and shows that in this case, the implementation classes for different invocations |
|
812 are indeed different: |
|
813 </p> |
|
814 <pre><code> |
|
815 var RunnableImpl1 = Java.extend(java.lang.Runnable, function() { print("I'm runnable 1!") }) |
|
816 var RunnableImpl2 = Java.extend(java.lang.Runnable, function() { print("I'm runnable 2!") }) |
|
817 var r1 = new RunnableImpl1() |
|
818 var r2 = new RunnableImpl2() |
|
819 r1.run() |
|
820 r2.run() |
|
821 print("We share the same class: " + (r1.class === r2.class)) |
|
822 </code></pre> |
|
823 <p> |
|
824 prints: |
|
825 </p> |
|
826 <pre><code> |
|
827 I'm runnable 1! |
|
828 I'm runnable 2! |
|
829 We share the same class: false |
|
830 </code></pre> |
|
831 <p> |
|
832 As you can see, the major difference here is that we moved the implementation object into the invocation of <code>Java.extend</code> |
|
833 from the constructor invocations – indeed the constructor invocations now don't even need to take an extra parameter! Since |
|
834 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 |
|
835 longer share the same class – every invocation of <code>Java.extend()</code> with a class-specific implementation object triggers |
|
836 the creation of a new Java adapter class. |
|
837 </p> |
|
838 <p> |
|
839 Finally, the adapter classes with class-bound implementations can <i>still</i> take an additional constructor parameter to further |
|
840 override the behavior on a per-instance basis. Thus, you can even combine the two approaches: you can provide part of the implementation |
|
841 in a class-based JavaScript implementation object passed to <code>Java.extend</code>, and part in another object passed to the constructor. |
|
842 Whatever functions are provided by the constructor-passed object will override the functions in the class-bound object. |
|
843 </p> |
|
844 <pre><code> |
|
845 var RunnableImpl = Java.extend(java.lang.Runnable, function() { print("I'm runnable 1!") }) |
|
846 var r1 = new RunnableImpl() |
|
847 var r2 = new RunnableImpl(function() { print("I'm runnable 2!") }) |
|
848 r1.run() |
|
849 r2.run() |
|
850 print("We share the same class: " + (r1.class === r2.class)) |
|
851 </code></pre> |
|
852 <p> |
|
853 prints: |
|
854 </p> |
|
855 <pre><code> |
|
856 I'm runnable 1! |
|
857 I'm runnable 2! |
|
858 We share the same class: true |
|
859 </code></pre> |
698 <hr> |
860 <hr> |
699 <a name="jsoverload" id="jsoverload"></a> |
861 <a name="jsoverload" id="jsoverload"></a> |
700 <h3>Overload Resolution</h3> |
862 <h3>Overload Resolution</h3> |
701 <p>Java methods can be overloaded by argument types. In Java, |
863 <p>Java methods can be overloaded by argument types. In Java, |
702 overload resolution occurs at compile time (performed by javac). |
864 overload resolution occurs at compile time (performed by javac). |
703 When calling Java methods from a script, the script |
865 When calling Java methods from Nashorn, the appropriate method will be |
704 interpreter/compiler needs to select the appropriate method. With |
866 selected based on the argument types at invocation time. You do not need |
705 the JavaScript engine, you do not need to do anything special - the |
867 to do anything special – the correct Java method overload variant |
706 correct Java method overload variant is selected based on the |
868 is selected based automatically. You still have the option of explicitly |
707 argument types. But, sometimes you may want (or have) to explicitly |
869 specifying a particular overload variant. Reasons for this include |
708 select a particular overload variant.</p> |
870 either running into a genuine ambiguity with actual argument types, or |
|
871 rarely reasons of performance – if you specify the actual overload |
|
872 then the engine doesn't have to perform resolution during invocation. |
|
873 Individual overloads of a Java methods are exposed as special properties |
|
874 with the name of the method followed with its signature in parentheses. |
|
875 You can invoke them like this:</p> |
709 <pre><code> |
876 <pre><code> |
710 // <a href="source/overload.js">overload.js</a> |
877 // <a href="source/overload.js">overload.js</a> |
711 |
878 |
712 var out = java.lang.System.out; |
879 var out = java.lang.System.out; |
713 |
880 |
714 // select a particular print function |
881 // select a particular print function |
715 out["println(java.lang.Object)"]("hello"); |
882 out["println(Object)"]("hello"); |
716 </code> |
883 </code> |
717 </pre> |
884 </pre> |
|
885 <p> |
|
886 Note that you normally don't even have to use qualified class names in |
|
887 the signatures as long as the unqualified name of the type is sufficient |
|
888 for uniquely identifying the signature. In practice this means that only |
|
889 in the extremely unlikely case that two overloads only differ in |
|
890 parameter types that have identical unqualified names but come from |
|
891 different packages would you need to use the fully qualified name of the |
|
892 class. |
|
893 </p> |
|
894 <hr> |
|
895 <a name="dataTypeMapping" id="dataTypeMapping"></a> |
|
896 <h3>Mapping of Data Types Between Java and JavaScript</h3> |
|
897 <p> |
|
898 We have previously shown some of the data type mappings between Java and JavaScript. |
|
899 We saw that arrays need to be explicitly converted. We have also shown that JavaScript functions |
|
900 are automatically converted to SAM types when passed as parameters to Java methods. Most other |
|
901 conversions work as you would expect. |
|
902 </p> |
|
903 <p> |
|
904 Every JavaScript object is also a <code>java.util.Map</code> so APIs receiving maps will receive them directly. |
|
905 </p> |
|
906 <p> |
|
907 When numbers are passed to a Java API, they will be converted to the expected target numeric type, either boxed or |
|
908 primitive, but if the target type is less specific, say <code>Number</code> or <code>Object</code>, you can only |
|
909 count on them being a <code>Number</code>, and have to test specifically for whether it's a boxed <code>Double</code>, |
|
910 <code>Integer</code>, <code>Long</code>, etc. – it can be any of these due to internal optimizations. Also, you |
|
911 can pass any JavaScript value to a Java API expecting either a boxed or primitive number; the JavaScript specification's |
|
912 <code>ToNumber</code> conversion algorithm will be applied to the value. |
|
913 </p> |
|
914 <p> |
|
915 In a similar vein, if a Java method expects a <code>String</code> or a <code>Boolean</code>, the values will be |
|
916 converted using all conversions allowed by the JavaScript specification's <code>ToString</code> and <code>ToBoolean</code> |
|
917 conversions. |
|
918 </p> |
|
919 <p> |
|
920 Finally, a word of caution about strings. Due to internal performance optimizations of string operations, JavaScript strings are |
|
921 not always necessarily of type <code>java.lang.String</code>, but they will always be of type <code>java.lang.CharSequence</code>. |
|
922 If you pass them to a Java method that expects a <code>java.lang.String</code> parameter, then you will naturally receive a Java |
|
923 String, but if the signature of your method is more generic, i.e. it receives a <code>java.lang.Object</code> parameter, you can |
|
924 end up with an object of private engine implementation class that implements <code>CharSequence</code> but is not a Java String. |
|
925 </p> |
718 <hr> |
926 <hr> |
719 <a name="engineimpl" id="engineimpl"></a> |
927 <a name="engineimpl" id="engineimpl"></a> |
720 <h2>Implementing Your Own Script Engine</h2> |
928 <h2>Implementing Your Own Script Engine</h2> |
721 <p>We will not cover implementation of JSR-223 compliant script |
929 <p>We will not cover implementation of JSR-223 compliant script |
722 engines in detail. Minimally, you need to implement the |
930 engines in detail. Minimally, you need to implement the |