Generic array factory in Java: receipt for disaster

4 11 2010

Let’s implement a generic factory method for arrays in Java like this:

static <T> T[] createArray(T... t) {
    return t;
}

We can use this method to create any array. For example an array of strings:

String[] strings = createArray("some", "thing");

Now let’s add another twist:

static <T> T[] crash(T t) {
    return createArray(t);
}

String[] outch = crash("crash", "me"); 

Running this code will result in a ClassCastException on the last line:

Exception in thread "main" java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to [Ljava.lang.String;

At first this seems strange. There is no cast anywhere here. So what is going on? Basically the Java compiler is lying at us: calling the crash method with string arguments, it tells us that we get back an array of strings. Now looking at the exception we see that this is not true. What we really get back is an array of objects!

Actually the Java compiler issues a warning on the createArray call in the crash method:

Type safety : A generic array of T is created for a varargs parameter

This is how it tells us about its lying: “Since I don’t know the actual type of T, I’ll just return an array of Object instead.” I thinks this is wrong. And others seem to think along the same lines.

About these ads

Actions

Information

4 responses

5 11 2010
Tweets that mention Generic array factory in Java: receipt for disaster « Michid’s Weblog -- Topsy.com

[...] This post was mentioned on Twitter by Planet Scala, Planet Lang. Planet Lang said: [Scala] Generic array factory in Java: receipt for disaster: Let’s implement a generic factory method for arrays… http://bit.ly/cszx6k [...]

11 11 2010
N

Java arrays are covariant, so this should not be a surprise, *particularly* not when the compiler even warns you.
Now, we can agree that covariant arrays are bad, but that’s been the state of Java since 1.0

11 11 2010
michid

This does not change my point: the compiler lies. At least it warns about its untruthfulness .

I understand that the issue at hand is an unfortunate interplay between covariant arrays, generic types and implementing varargs through arrays. But making the compiler lie seem plain wrong to me. That code should not compile at all!

8 03 2011
Thomas

In Java, object arrays are currently covariant. Actually they are, but only when reading. To solve the problem, the ‘read’ and the ‘write’ type would need to be specified, so instead of (Object[] t) it would be (Object/String[] t) which means read objects, but store strings. This doesn’t solve the problem above however.

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




Follow

Get every new post delivered to your Inbox.

%d bloggers like this: