Skip to content

A short Java test, a long Java rant

January 29, 2010

I recently came across a few little SCJP-style Java tests. There’s nothing particularly special about them, but they got me thinking about some aspects of the language that I hadn’t really thought about before. Here’s the first; I wonder what you’ll make of it…

class ExA extends RuntimeException {}

class ExB extends ExA {}

public class ExceptionTest {

   void doStuff() throws ExA {
      throw new ExB();
   }

   @Test
   public void whichCatch() {
   try {
     doStuff();
   } catch (ExB e) {
      System.out.println("B");
   } catch (ExA e) {
      System.out.println("A");
   } finally {
      System.out.println("F");
   }
}

What do you think the output will be? The original had multiple choice answers, but really you need to decide on two things:

  1. Which catch block will catch the exception?
  2. Will the finally be called?

Once you’re done thinking about that, here’s the second:

public class CollectionsTest {

   @Test
   public void listSet() {

      List<String> list = new java.util.ArrayList<String>();
      Set<String> set = new HashSet<String>();

      list.add("hello");
      set.add("hello");

      System.out.println(list.equals(set));
      System.out.println(list.contains(set));

      set.add("hello");

      for (String s : set) {
         System.out.println(s);
      }
   }
}

Again, I’ll leave out the multiple choice answers; all you need to do is work out one or more of whether:

  1. The list and set are equal.
  2. The list contains the set.
  3. The second set.add() throws a runtime exception.
  4. The set, when printed,  has one or two strings in it.

Catching exceptions

Time for some answers. The short answer is:

  1. The first catch block will catch the exception
  2. The finally will be called

And so the output is “BF” (except on multiple lines, obviously).

What’s your point?

If the first catch block catches the exception, then the exception type is being checked at runtime; all the compiler knows is that an ? extends ExA is going to be thrown. But that implies that exception-catching relies on mechanisms like instanceof, which we know are junk (where junk is indicative of poor software design, poor runtime performance, and probably a whole bunch of other stuff). This in turn implies that throwing exceptions is bad, and should be avoided, right? But I’ve seen people much more knowledgeable than I am post examples of exception usage that in turn allows exceptionally clean code.

I guess the bottom line, for me, is that I’d never really thought of exception handling as sharing attributes of the instanceof mechanism, and assuming that I’m even correct, I don’t think I’ll let it get in the way of me trying to write good, clean code that makes intelligent use of exceptions. The key word there being trying

Sets of Lists and Lists of Sets

I did slightly worse with this one. The correct answers are:

  1. The list and set are not equal. Lists are only equal to objects that (a) are lists and (b) have the same contents in the same order, so whilst the set passes (b), it won’t pass (a).
  2. The list does not contain the set. The list contains String objects; the set is a Set. list.containsAll(set) would’ve returned true, but that’s not what we called.
  3. The second set.add() doesn’t throw a runtime exception. As this set already contains the element, the call leaves the set unchanged and returns false.
  4. The set, when printed,  has one string in it.

So the output is “false false hello”, although again separated by newlines and not spaces…

You’d better have something interesting to say now

I imagine that was at best light revision for most of you, and more likely tediously trivial. Putting aside the fact that I’d forgotten that lists are only equal to other lists, what I want to know is why does list.contains(set) compile? This is a post-Java 5, generic-enabled Collection. Surely the signature of contains is the same as add, and that our Set can only have Strings added to it, and therefore contain only Strings?

It does compile, and run, and I’m sure that there’s a good reason why the Java 5 creators kept

boolean contains(Object o)

when add is

boolean add(E e)

but I can’t think of one. Certainly not at this time on a Friday evening. Then again, that’s probably why I wasn’t in charge of putting generics into Java 5 in the first place.

It also crossed my mind that, if contains() were strongly typed, then we wouldn’t need a containsAll(); we could just overload contains() with a method that took a Collection. Of course, that’s a stupid idea; I’ll leave it as an exercise as the reader to work out why.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: