Charting Unknown Waters in JDK 1.4

ondering what I would dig up in the JDK 1.4 source code, I recently started looking through the classes in the java.util.* package?without even the subpackages. That alone kept me busy for most of an afternoon, and although I have not finished exploring that J2SE release yet, I already have enough material for several articles. The following are some of the gems I discovered right away.

Did You Know toString() was Broken for Collections?
In the collection classes, all hell breaks loose when you try to call toString() on a collection that contains itself. For example, consider the following code:

  import java.util.Hashtable;  public class HashtableTest {    public static void main(String[] args) {      Hashtable ht = new Hashtable();      ht.put("Heinz", "Kabutz");      ht.put(ht, "all");      ht.put("all", ht);      ht.put(ht, ht);      try {        System.out.println(ht);      } catch (StackOverflowError e) {        System.out.println("Caused Stack Overflow Error!");      }    }  }

Running this program under JDK 1.3 or older versions generates a stack overflow. In JDK 1.4, however, the output is:

  {Heinz=Kabutz, all=(this Map), (this Map)=all, (this Map)=(this Map)}

This same principle applies to the other collections in JDK 1.4.

Is it a good idea to use a Hashtable as a key, you might ask. Dont forget what happens when the hash code of a key changes during its life (see Issue 031 of The Java(tm) Specialists’ Newsletter). Each time a Hashtable changes, its hash code changes as well. So you should not use it as a key. The question I have is why?despite the seemingly limitless amount of stupid code written every day?the people at Sun didn’t anticipate programmers adding a collection to itself.Introducing RandomAccess, A New Tag Interface
A highly paid software developer once wrote code along the lines of the following snippet. Take a moment to thoroughly read the code and understand it:

  /** @author Mr M.O.Nument */  import java.util.*;  public class ListSearching {    private List names = new LinkedList();    public void f() {      for (int i=0; iif (names.get(i) == "Heinz")          System.out.println("Found it");      }    }    private int size() {      int result = 0;      Iterator it = names.iterator();      while(it.hasNext()) {        result++;        it.next();      }      return result;    }  }

Dont be too quick to judge the programmer. In his defense, a lot of code had to go between f() and size(), so the problem was not as obvious as it now appears. Also, the list was always very short, so performance was not an issue either.

JDK 1.4 introduces a new tag interface called RandomAccess (like java.io.Serializable) into the java.util package. It allows classes such as Collections to optimize their algorithms in the case where the following code:

  for (int i=0, n=list.size(); i < n; i++)    list.get(i);

runs faster than the following loop:

  for (Iterator i=list.iterator(); i.hasNext(); )    i.next();

What I found interesting was that the algorithms always treat the collections as RandomAccess unless they are bigger than some threshold. This makes a lot of sense, because I have often found algorithms that I thought to be faster for linked lists actually being slower (see Issue 024 of The Java(tm) Specialists' Newsletter). The values of the thresholds are of course not configurable and are approximations based on empirical data (i.e., experiments) that would work well with the LinkedList.RuntimeException Specifications: An Admission of Guilt?
All over the JDK 1.4 java.util.* package, I have noticed that the RuntimeExceptions are now also specified in the @throws clause of the JavaDocs. Bruce Eckel and I exchanged quite a few e-mails debating the current exception model. We ended up wondering whether it perhaps was fundamentally flawed. For example, java.io.IOException has more than 30 subclasses that each could be the actual exception being thrown. What good is that? When you see that a method throws IOException, what is actually being thrown and how do you deal with it?

I think that checked exceptions should be scrapped. They don't work. They cause bad code, such as the following:

  while(true) {    try {      Thread.sleep(1000);      // do some other work    } catch (Exception e) {}  }

Checked exceptions are responsible for more sloppy code and bugs than any other construct in the Java language. C# does not have checked exceptions, neither does C++. Why does Java continue to be encumbered by them? I think declaring as comments the runtime exceptions that a method could throw is a step in the right direction.

More to Come
Look for other interesting little snippets I've discovered in my upcoming articles.

Editor's Note: This article first appeared in Dr. Kabutz's The Java(tm) Specialists' Newsletter under the title Charting Unknown Waters in JDK 1.4 Part I. To subscribe, send an email to [email protected].

Share the Post:
Share on facebook
Share on twitter
Share on linkedin

Overview

The Latest

microsoft careers

Top Careers at Microsoft

Microsoft has gained its position as one of the top companies in the world, and Microsoft careers are flourishing. This multinational company is efficiently developing popular software and computers with other consumer electronics. It is a dream come true for so many people to acquire a high paid, high-prestige job

your company's audio

4 Areas of Your Company Where Your Audio Really Matters

Your company probably relies on audio more than you realize. Whether you’re creating a spoken text message to a colleague or giving a speech, you want your audio to shine. Otherwise, you could cause avoidable friction points and potentially hurt your brand reputation. For example, let’s say you create a

chrome os developer mode

How to Turn on Chrome OS Developer Mode

Google’s Chrome OS is a popular operating system that is widely used on Chromebooks and other devices. While it is designed to be simple and user-friendly, there are times when users may want to access additional features and functionality. One way to do this is by turning on Chrome OS