Creating and calling objects

For the purposes of this introduction, it really makes no difference what Java objects we use, so let's use a little class called GregorianCalendar from the standard Java libraries:
  set cal [java::new java.util.GregorianCalendar]
The the java::new command accepts the fully-qualified name of a Java class, and produces a new object using the appropriate constructor. Since the GregorianCalendar class is in the java.util package, its fully-qualified name is java.util.GregorianCalendar. The interpreter will print something like "java0x1", which is a reference to the java object we just created.

Let's just verify that this object is what we think it is:

  java::info class $cal

(Which returns java.util.GregorianCalendar.) The java::info command performs introspection on a Java object. For example, we can also find out the object's superclass:

  java::info superclass $cal
Other useful options include fields, which lists the public variables of an object, and methods, which lists the methods of an object. (See the java::info man page.)
What's a Java package?
Java has packages too, although they are more pervasive and structured than in Tcl. Java requires that every class be located in a package, such as java.util (all of the JDK is located within the java package), or tcl.lang (where the Tcl Blend and Jacl classes are located). The directory structure reflects the package structure, so that the class java.util.GregorianCalendar will be located in the directory java/util/GregorianCalendar, relative to what is know as the classpath. (Let's avoid talking about the classpath until later.)

(By the way, you don't use the Tcl package to load Java packages or classes. Java will find and load the classes automatically when it needs them.)

We can now call methods on this object, using an object-oriented style of syntax. Since we set the variable cal the returned object, we can, for example, go:
  $cal toString
Well, the printed result is less than helpful, but you can at least see that there's useful information in there! (Every Java object has a toString method, which produces a string containing a "useful" description of the object.) Let's try something else: first we get the time from the calendar with the getTime method, and then we print it:
  set currentTime [$cal getTime]
  $currentTime toString
This will print something like "Wed Jul 29 18:16:27 PDT 1998." (What's the class of currentTime?) By the way, the value in the calendar is not the current system clock, just the clock at the time we created the calendar -- if you execute the above code again in five minutes time, it will print exactly the same thing. You can, however, manipulate the time in the calendar like this:
  $cal set 1998 8 15 14 0
  set currentTime [$cal getTime]
  $currentTime toString
Which will print the time this tutorial starts at the Tcl/Tk conference -- don't forget to register :-). The arguments to this version of the set method are the year, month, day, hours, and minutes. (January is month zero, don't ask us why.)

You may have noticed that we have been assigning Java objects to Tcl variables, even though the java object returns something that looks like an identifier we can use to reference it (like "java0x2"). We don't always have to assign the result from a call to Java to a variable -- but we do need to ensure that the Tcl interpreter always has at least one reference to that object, so that the object won't get garbage-collected while you still need it.

For example, this is fine:

  [$cal getTime] toString
The object returned by getTime has the toString call made on it while the interpreter still has a reference to it, so it won't be garbage-collected until we're done with it. If however, we were to do this:
  set id [lindex [split [$cal getTime] x] 1]
  java0x$id toString
then there's a good chance that you'll lose the object and get a run-time error. Why you would want to do this is anybody's guess -- but the lesson is that Java objects need to be referenced or you'll lose them. Tcl Blend does provide two commands that allow you to increment and decrement an object's reference count: java::lock and java::unlock. Our preference is simply to treat Java objects like proper opaque object references, and not as Tcl strings or lists.
Bogon alert!
Always assign the return result from a call to Java to a Tcl variable if you intend to keep that object.

Summary of this section