- Notifications
You must be signed in to change notification settings - Fork0
Converting Script Values to Java
When values (including both primitives and objects) are passed back as parameters to Java methods, they are often converted. Nashorn supports a wide variety of automatic value conversions, that seek to incorporate both the flexibility of ECMAScript value conversion system as well as the rules of Java. In addition, in some situations explicit conversion operations are possible. We describe all below.
When a method on a Java object is invoked, the arguments are converted to the formal parameter types of the Java method using all allowed ECMAScript conversions. This can be surprising, as in general, conversions from string to number will succeed according to Standard's section 9.3 "ToNumber" and so on; string to boolean, number to boolean, Object to number, Object to string all work. In detail the supported conversions are as follows:
Java type | Conversion |
---|---|
boolean | As perECMAScript 9.2ToBoolean conversion. Colloquially, as if you applied!! to the value. |
byte ,short ,int ,float ,long ,double | As perECMAScript 9.3ToNumber conversion. Colloquially, as if you applied+ to the value to obtain a JavaScript number and then if necessary used Java casting to convert to the target type. |
char | If the value isnull ,(char)0 . If the value is a number between 0-65535 then(char)i , wherei is the value of the number truncated to integer. Otherwise the value is converted to a string usingECMAScript 9.8ToString conversion. If the result of the conversion isnull , then(char)0 . Otherwise if the string length is not exactly 1, aTypeError is thrown. Otherwise, the first character of the string is returned. |
String ,CharSequence | null is passed as-is, otherwiseECMAScript 9.8ToString conversion is used. |
Number | null is passed as-is, but the concrete type might be eitherInteger orDouble . |
Character | aschar , exceptnull is passed as-is and not converted to(char)0 . |
Byte ,Short ,Int ,Float ,Long ,Double | null is passed as-is, otherwise as for the primitive types. Undefined values are converted to eitherNan for floats and doubles ornull for integer types. |
lambda types | If the type is a Java lambda type (an interface or abstract class with a single method), you can pass in an ECMAScript function and Nashorn will do the right thing, and create an adapter for the lambda type. Nashorn is even more versatile than Java though, you can pass a function for a type that hasmultiple abstract methods, but they all share the same name (the name is overloaded.) In that case, the passed function will be used as the implementation for all the overloads and must analyze the number and types of its parameters to decide which overload was invoked. |
Map | null is passed as-is. Any script object will be passed as-is, as they all implement theMap interface with string keys. This is true of script arrays too. Primitive types cannot be passed (they are not run automatically through ECMAScriptToObject conversion.) |
List ,Collection ,Queue ,Dequeue | null is passed as-is. For native script arrays, an adapter is returned that exposes the array. Note that with ECMAScript arrays,push andpop operate at the end of the array, while in JavaDeque they operate on the front of the queue and as such the Java dequeuepush andpop operations will translate tounshift andshift script operations respectively, while JavaaddLast andremoveLast will translate topush andpop . Primitive values and objects that are not arrays can not be passed. It is possible to enforce converting other array-like objects to lists and queues with explicit call toJava.to , see later. |
Java array types | Script arrays are converted to Java arrays using per-component conversions. If the target Java array type is multidimensional, components are recursively converted, so it will properly convert arrays-of-arrays etc. Objects that are not native script arrays can not be passed. It is possible to enforce converting other array-like objects to Java arrays with explicit call toJava.to , see later. |
Object | if the Java parameter type is justObject , values are passed as they are. JavaScript primitive values are passed asBoolean (for booleans),Number (for numbers), andCharSequence (for strings). Strings are not necessarily a JavaString but they are always aCharSequence . Numbers will usually beInteger orDouble . Script objects will be passed as object implementing both Nashorn'sJSObject interface and also theMap interface. This is true of script arrays too –- if you need arrays to implementList instead, you'll need to useJava.asJSONCompatible explicit conversion method found in the built-inJava global object. |
The built-inJava object contains two methods useful for explicit specialized conversions to Java types:Java.asJSONCompatible
andJava.to
.
This method is useful if you need to pass a script array (or an object graph containing script arrays recursively) such that array adapters should exposeList
interface instead of theMap
interface that is by default exposed by all script objects to Java. The name of the method stems from the fact that various Java JSON libraries typically have this expectation. Unfortunately, it is also impossible for a single Java class to implement bothMap
andList
interfaces, hence we are providing the developer here with a choice of how to represent script arrays in Java.
While Nashorn automatically converts native script arrays (those of script classArray
) to either Java arrays or toCollection
,List
,Queue
, andDeque
interface, it won't do that for other objects that might still be "array-like". A script object is array-like if it has alength
property andpush
,pop
,shift
,unshift
, andsplice
methods, with the expectation that all of them have same behaviors as the native script arrays. UsingJava.to
you can explicitly convert such array-like objects to Java arrays or collections:
varsomeArrayLike= ...javaObj.methodExpectingIntArray(Java.to(someArrayLike,Java.type("int[]"))
If converting to lists or queues, the adapter will callsplice
to add or remove elements in the middle of the list,push
, andunshift
to add elements to the start and end of the list, andpop
andshift
to remove elements from the start and end of the list.
Note that with ECMAScript arrays,push
andpop
operate at the end of the array, while in JavaDeque
they operate on the front of the queue and as such calls to the Java dequeueaddFirst
/push
andremoveFirst
/pop
methods will translate tounshift
andshift
script methods respectively, while JavaaddLast
andremoveLast
will translate to scriptpush
andpop
.