varatis
varatis

Reputation: 14750

Why can't ArrayStoreExceptions be caught by the Java compiler?

I understand what an ArrayStoreException is. My question is: why isn't this caught by the compiler?

This might be an odd example, but say you do this:

    HashMap[] h = new LinkedHashMap[4];
    h[0] = new PrinterStateReasons();

Why can't the compiler recognize that this isn't valid?

Upvotes: 2

Views: 128

Answers (4)

T.J. Crowder
T.J. Crowder

Reputation: 1075755

Because the information you've given the compiler allows what you're doing. It's only the runtime state that's invalid. Your h variable is declared as being a HashMap[], which means that as far as h is concerned, anything implementing HashMap is a valid element. PrinterStateReasons implements HashMap, and so h[0] = new PrinterStateReasons(); is a perfectly valid statement. Similarly, since LinkedHashMap implements HashMap, the statement HashMap[] h = new LinkedHashMap[4]; is a perfectly valid statement. It's only at runtime that you try to store a PrinterStateReasons object as an element in a LinkedHashMap array, which you can't do as it isn't assignment-compatible.

The two statements you've given are contiguous, but of course the generalized reality is far more complex. Consider:

HashMap[] h = foo.getHashMapArray();
h[0] = new PrinterStateReasons();

// ... elsewhere, in some `Foo` class -- perhaps compiled
// completely separately from the code above, perhaps
// even by a completely different team and even a different
// compiler --  and only combined with the code above at runtime...

public HashMap[] getHashMapArray() {
    return new LinkedHashMap[4];
}

Upvotes: 4

Stephen C
Stephen C

Reputation: 719679

The Java Language Specification says that this is valid program. A compiler that flagged it as an error is not implementing the specification, and therefore is not a compliant Java compiler. The real harm of a non-compliant compiler is that it leads to people writing source code that is not portable; e.g. compiles with one compiler but not another.

The best that a compiler could legally do is to warn you that the code will always throw an exception. For instance, some compilers will warn you about null pointer exceptions that will always be thrown. I guess they don't do this in the array index case because the analysis is more complicated, and the mistake is made less often.

Upvotes: 0

JB Nizet
JB Nizet

Reputation: 692231

What the compiler can't catch is when you refer to a specific type array using a more generic type array:

String[] s = new String[10];
Object[] o = s;
o[0] = new Integer(5);

The compiler can't detect it because it has no way, from the variable declaration, to know the actual type of the array.

Note that you won't have this problems with generic collections, because although a String[] is also an Object[], a List<String> is not a List<Object>. One more reason to prefer collections over arrays.

Upvotes: 0

KarlP
KarlP

Reputation: 5191

Well, I suppose that a smart compiler would be able to statically analyse that h can never be anything else than a LinkedHashmap[] at line 2.

But without that (potentially rather complex analytics, perhaps not this simple case though) the compiler can't really know what is assigned to h. You can assign a PrinterStateReasons to a HashMap, just not to a LinkedHashMap.

Upvotes: 0

Related Questions