clamp
clamp

Reputation: 34026

why does java allow this?

it is syntactically legal to do this:

String [] s = new String[1];
Object [] o = s;

o[0] = new Integer(42);

but of course it will crash at runtime.

my question is: what is the point of allowing this assignment in the first place?

Upvotes: 3

Views: 270

Answers (6)

Flash
Flash

Reputation: 16713

Generally the compiler can't tell if o has been assigned as String[]. Consider this:

String[] s = new String[1];
Object[] o;

if (complexFunction(System.currentTimeMillis())) {
  o = s;
} else {
  o = new Integer[1];
}

o[0] = 42;

The compiler won't know at design time what type o is going to take - so it just allows the assignment.

Upvotes: 0

Michael Borgwardt
Michael Borgwardt

Reputation: 346307

The problem is the assignment Object [] o = s; - I assume that's what you mean by "this".

The technical term is array covariance, and without it, you could not have code that deals with arrays generically. For example, most of the non-primitive-array methods in java.util.Arrays would be useless as you could only use them with actual Object[] instances. Obviously, this was considered more important by the designers of Java than complete type safety.

There is an alternative solution, which you see when looking at Java's generics introduced in Java 5: explicit covariance via wildcards. However, that results in considerable added complexity (see the constant stream of questions about the ? wildcard), and Java's original designers wanted to avoid complexity.

Upvotes: 8

aroth
aroth

Reputation: 54816

The point of allowing that kind of assignment is that disallowing it would make things like the following impossible:

ArrayList[] lists = new ArrayList[10];
lists[0] = new ArrayList();

List[] genericLists = lists;
lists[0].add("someObject");

If the compiler forbids your String -> Object case, then it would also have to forbid ArrayList -> List and any other instance of assigning from a subclass to one of its superclass types. That kind of makes a lot of the features of an object-oriented language such as Java useless. Of course, it's much more typical to do things like:

List[] lists = new List[10];
lists[0] = new ArrayList();
lists[0].add("someObject");

But regardless, the compiler can't filter out these cases without simultaneously disallowing many useful and legitimate use-cases, so it's up to the programmer to make sure that what they are doing is sane. If what you want is an Object[], then declare your variable as such. If you declare something as String[], cast it to an Object[], and then forget that what you really have is a String[], then that is simply programmer error.

Upvotes: 2

Miguel Ping
Miguel Ping

Reputation: 18347

The assignment must be allowed because the compiler cannot infer if the array will hold (or will not hold) only strings at runtime. It throws an [ArrayStoreException][1] which is checked at runtime.

Consider this:

String [] s = new String[1];
Object [] o = s;

o = new Integer[1];

o[0] = new Integer(1);

This situation is valid and runs OK. To give a more broader perspective, IMHO Arrays are a low-level leaky abstraction in Java.

Upvotes: 0

Augusto
Augusto

Reputation: 29927

It's not allowed, you get a java.lang.ArrayStoreException: java.lang.Integer when you run that code

The compiler allows it, because you're casting a String[] to Object[], which is correct. This is similar to

Integer i = new Integer(10);
Object o = i;
String s = (String) o;

The compiler doesn't complain, but you get a ClassCastExeption at runtime.

Upvotes: 1

Ignacio Vazquez-Abrams
Ignacio Vazquez-Abrams

Reputation: 798744

The compiler can't know (without static analysis) that o is actually a String[] and so allows the assignment even though it fails at runtime. There's nothing preventing a e.g. Integer[] to be assigned to o, it just doesn't happen.

Upvotes: 0

Related Questions