Mik378
Mik378

Reputation: 22171

Warning unnecessary with generic collections?

I wonder why Java compiler doesn't trust in this line of code :

List<Car> l = new ArrayList();

and expects to have a typed ArrayList :

List<Car> l = new ArrayList<Car>();

Indeed, compiler indicates an unchecked assignment with the first case.

Why doesn't compiler see that this ArrayList() has just been created and so it's impossible to find already in it some objects other than 'Car'?

This warning would make sense if the untyped ArrayList was created before but doesn't in this case ...

Indeed, since List is typed as 'Car', all futures "l.add('object')" will be allowed only if 'object' is a 'Car'. => So, according to me, no surprise could happen.

Am I wrong ?

Thanks

Upvotes: 1

Views: 162

Answers (2)

Voo
Voo

Reputation: 30216

To add to Stephen C's really good answer (mostly because writing this as a comment would be really cumbersome, sorry), this problem is actually explicitly mentioned in the JLS:

Discussion

Variables of a raw type can be assigned from values of any of the type's parametric instances.

For instance, it is possible to assign a Vector<String> to a Vector, based on the subtyping rules (§4.10.2).

The reverse assignment from Vector to Vector<String> is unsafe (since the raw vector might have had a different element type), but is still permitted using unchecked conversion (§5.1.9) in order to enable interfacing with legacy code. In this case, a compiler will issue an unchecked warning.

Why they didn't special case this particular case? Because adding special cases to an implementation isn't something you do if you don't have to and the "correct" solution doesn't add any particular problems (apart from some writing effort which they presumably didn't think was too important).

Also every special case means that the compiler gets more complicated (well generally speaking at least and in this case certainly) - considering how simple javac is on the whole, I'd think it's not unlikely that having a simple, fast compiler was also one of the design goals.

Upvotes: 2

Stephen C
Stephen C

Reputation: 718856

Why doesn't compiler see that this ArrayList() has just been created and so it's impossible to find already in it some objects other than 'Car'?

The simple answer is "Because it is not allowed to."

The compiler has to implement the Java Language Specification. If some compiler writer goes and adds a bunch of smarts to the compiler to allow things that "everyone" knows are safe, then what he's actually done is to introduce a portability problem. Code compiled and tested with this compiler will give compilation errors when compiled with a dumb (or more accurately, strictly conformant) Java compiler.

So why doesn't the JLS allow this? I can think of a couple of possible explanations:

  • The JLS writers didn't have time to add this to the specification; e.g. to consider all of the ramifications on the rest of the specification.
  • The JLS writers couldn't figure out a sound way to express this in the specification.
  • The JLS writers didn't want to put something into the specification that they weren't sure was implementable in a real world compiler ... without being too burdensome on the compiler writer.

And then there is the associated question of whether a compiler could implement such a check. I'm not qualified to answer that ... but I know enough about the problem to realize that it is not necessarily as simple to solve as one might imagine.

Upvotes: 3

Related Questions