Types and conversion

We have just seen how to call methods on a Java object. Let's explore this further.

By default, the value returned from a call to Java is converted to a Tcl object if it is a primitive Java data type, such as int, long, float, double, or boolean. In addition, objects of the java.lang.String class are converted to a Tcl string object.

For example, previously we wrote

  $cal toString
to get a representation of the calendar object, which printed a (Tcl) string on your console. To get a handle to the actual Java String object, use
  set str [$cal -noconvert toString]
(Use java::info to take a look at the returned object.) In this example, the -noconvert option caused Tcl Blend to not convert the java.lang.String object returned by the toString object into a Tcl string, but to return a reference to the original Java object.

On calls that return primitive Java values, -noconvert will cause Tcl Blend to wrap the primitive value in a Java object. For example, the getFirstDayOfWeek method returns an int, but if we write

  set num [$cal -noconvert getFirstDayOfWeek]
we will get a Java object of class java.lang.Integer instead of printing the numeral 1. (1 means Sunday -- in European time zones, this method will return 2 for Monday.)
Java wrappers
Java contains a whole set of wrapper classes for primitive types. These wrapper classes, in the package java.lang, are used to pass primitive data polymorphically (that is, in situations when we may not know in advance what type of data is contained, such as when storing elements in a hash-table). They also include methods for converting primitive types to and from strings.

In a similar manner, Tcl Blend converts Tcl objects into Java objects or primitive types when we pass them as arguments to Java methods. Thus, when we wrote

  $cal set 1998 8 15 14 0
the Tcl strings "1998," "8," and so on were converted into Java int values and passed to the set method. Of course, if the argument is a Java object, then Tcl Blend just passes that Java object to the method.

This can lead to ambiguity, since Java allows methods to be overloaded by argument type. For the sake of example, suppose that we wanted to search for the substring "YEAR" in the string we obtained from the calendar object. We might try

  set yearIndex [$str indexOf YEAR]
Oops! Tcl Blend complains about an "ambiguous method signature." That's because there are two versions of the indexOf method with one argument! (See the documentation for indexOf(int) and indexOf(String).) To disambiguate the method call, we must go:
  set yearIndex [$str {indexOf String} YEAR]
The Tcl list {indexOf String} is called a signature, and it tells Tcl Blend exactly which method to use: the method indexOf with a single argument of type String. Now we can, say, get this substring and the year from it:
  $str substring $yearIndex [expr $yearIndex+9]
which returns YEAR=1998.
By the way
As a general rule, this kind of string processing is best done in Tcl. Tcl is designed from the ground up as a string processing language, and can in fact be substantially faster than Java. For some concrete measurements, see the paper Timing Trials II: More Experiments with Scripting Languages. (The results will, of course, vary widely with the quality of the Java compiler.)
Now, if Tcl Blend were as smart as you and me, it would have figured this out for itself, since calling the other version of this method:
  set yearIndex [$str {indexOf int} YEAR]
is clearly nonsensical, as you can't convert "YEAR" into an int. (If you try it, it produces a run-time error).

Bogon alert
The method resolver in Tcl Blend is very simple, and looks only at the number of arguments. We expect this is probably for performance reasons, but it is a little frustrating. If you are writing Java objects with the expectation that they will be called from Tcl, it's probably a good idea to avoid overloaded methods. For more on type resolution in Tcl Blend, see Mo Dejong's JMF paper in the proceedings of this conference.

You can use the -type flag to java::info to get the types of a method. We'll let you try that for yourself, but here's a little Tcl proc that makes the output easier to read:

  proc showMethods {objOrClass} {
    foreach {rtype atype _} [join [java::info methods -type $objOrClass]] {
      puts "$rtype [lindex $atype 0] ([lreplace $atype 0 0])"
    }
  }
  showMethods $cal

Summary of this section