Unreasonable bugs: type-based exceptions

When it comes to type systems, I don’t have hard and fast rules for what I like and what I don’t like. I enjoy some dynamic languages, some static languages. I pick which language to use (and consequently which typing system) based on the nature of the project I’m working on.

Usually, if I pick a strongly-typed language, it’s because I’m working on the type of program where I think type errors might be serious and complicated, and therefore I believe that static checking will help me out. Of course, all of this only applies if the language actually catches the type errors at compile time.

“But wait,” I can hear you saying, “don’t static languages always catch all type errors at compile time? Isn’t that the whole point?”

Oh yes, as far as I’m concerned it most certainly is the point. The single greatest advantage to working in a statically-typed language is that, in principle, type errors can be detected at compile time. Unfortunately, for two major languages, there exists type errors that are not caught until runtime. (And I’m not talking about C++ here!)

The problem goes something like this: in both C# and Java, if A is-a B, then A[] is-a B[]. In other words, if we have a function like

void messWithArray(B[] someArg) {...}

we are permitted to invoke it like so:

messWithArray(new A[10])

Now, if messWithArray only intends to read from the array, nothing will go wrong. Unfortunately, this can cause massive problems if messWithArray wants to assign new elements in our array.

To to prevent this from being an issue, the Java Virtual Machine performs run-time type checks on array assignments. Yup!

Here’s some code in Java that demonstrates this problem:
// CParent.java:
public class CParent {
}

// CChild1.java:
public class CChild1 extends CParent{
 
public void CChild1() { }
}

// CChild2.java:
public class CChild2 extends CParent{
 
public void CChild2() { }
 
public void doStuff() { }
}

// typefoo.java:
public class typefoo {
 
public static void main(String[] args) {
   
System.out.println(“Creating array of CChild2’s”);
   
CChild2[] a = new CChild2[10];
   
System.out.println(“Calling setElements on our array”);
    setElements
(a);
   
System.out.println(“Calling useElements on our array”);
    useElements
(a);
   
System.out.println(“All done!”);
 
}

  public static void setElements(CParent[] a) {
    a
[0] = new CChild1();
 
}

  public static void useElements(CChild2[] a) {
    a
[0].doStuff();
 
}
}

$ java typefooCreating array of CChild2'sCalling setElements on our array
Exception in thread "main" java.lang.ArrayStoreException: CChild1
  at typefoo.setElements(typefoo.java:14)
  at typefoo.main(typefoo.java:7)

Disgraceful.

Advertisements
Previous Post
Leave a comment

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: