JavaScript: The Definitive GuideJavaScript: The Definitive GuideSearch this book

22.5. LiveConnect Data Conversion

Java is a strongly typed language with a relatively large number of data types, while JavaScript is an untyped language with a relatively small number of types. Because of this major structural difference between the two languages, one of the central responsibilities of LiveConnect is data conversion. When JavaScript sets a Java class or instance field or passes an argument to a Java method, a JavaScript value must be converted to an equivalent Java value, and when JavaScript reads a Java class or instance field or obtains the return value of a Java method, that Java value must be converted into a compatible JavaScript value.[77]

[77]In addition, data conversion must happen when Java reads or writes a JavaScript field or invokes a JavaScript method. These conversions are done differently, however, and are described later in this chapter, when we discuss how to use JavaScript from Java. For now, we're considering only the data conversion that happens when JavaScript code interacts with Java, not the other way around.

Figure 22-2 and Figure 22-3 illustrate how data conversion is performed when JavaScript writes Java values and when it reads them, respectively.

Figure 22-2

Figure 22-2. Data conversions performed when JavaScript writes Java values

Figure 22-3

Figure 22-3. Data conversions performed when JavaScript reads Java values

Notice the following points about the data conversions illustrated in Figure 22-2:

Also notice these points about the conversions illustrated in Figure 22-3:

22.5.1. Wrapper Objects

Another important concept that you must grasp in order to fully understand Figure 22-2 and Figure 22-3 is the idea of wrapper objects. While conversions between most JavaScript and Java primitive types are possible, conversions between object types are generally not possible. This is why LiveConnect defines the JavaObject object in JavaScript -- it represents a Java object that cannot be directly converted to a JavaScript object. In a sense, a JavaObject is a JavaScript wrapper around a Java object. When JavaScript reads a Java value (a field or the return value of a method), any Java objects are wrapped and JavaScript sees a JavaObject.

A similar thing happens when JavaScript writes a JavaScript object into a Java field or passes a JavaScript object to a Java method. There is no way to convert the JavaScript object to a Java object, so the object gets wrapped. The Java wrapper for a JavaScript object is the Java class netscape.javascript.JSObject.

Things get interesting when these wrapper objects are passed back. If JavaScript writes a JavaObject into a Java field or passes it to a Java method, LiveConnect first unwraps the object, converting the JavaObject back into the Java object that it represents. Similarly, if JavaScript reads a Java field or gets the return value of a Java method that is an instance of netscape.javascript.JSObject, that JSObject is also unwrapped to reveal and return the original JavaScript object.

22.5.2. LiveConnect Data Conversion in Netscape 3

In Netscape 3, there was a bug in the way that LiveConnect converted Java values to JavaScript values: the value of a primitive field of a Java object was incorrectly returned as a JavaScript object, rather than as a JavaScript primitive value. For example, if JavaScript read the value of a field of type int, LiveConnect in Netscape 3 converted that value to a Number object, rather than to a primitive numeric value. Similarly, LiveConnect converted the value of Java boolean fields to JavaScript Boolean objects, rather than primitive JavaScript boolean values. Note that this bug occurred only when querying the values of Java fields. It did not occur when LiveConnect converted the return value of a Java method.

Number and Boolean objects in JavaScript behave almost, but not exactly, the same as primitive number and boolean values. One important difference is that Number objects, like all JavaScript objects, use the + operator for string concatenation rather than for addition. As a result, code like the following that uses LiveConnect in Netscape 3 can yield unexpected results:

var r = new java.awt.Rectangle(0,0,5,5);
var w = r.width;    // This is a Number object, not a primitive number.
var new_w = w + 1;  // Oops! new_w is now "51", not 6, as expected. 

To work around this problem, you can explicitly call the valueOf( ) method to convert a Number object to its corresponding numeric value. For example:

var r = new java.awt.Rectangle(0,0,5,5);
var w = r.width.valueOf( );  // Now we've got a primitive number.
var new_w = w + 1;          // This time, new_w is 6, as desired.

 


Library Navigation Links

Copyright © 2003 O'Reilly & Associates. All rights reserved.