Bober02
Bober02

Reputation: 15331

Java generics and casting

In Java generics, if you type

List<Object> l = new ArrayList<>();
List<String> l2 = l; //no casting works here

It won’t compile, reporting inconvertible types List<Object> to List<String>. However:

List<? extends Object> l = new ArrayList<>();
List<String> l2 = ( List<String> ) l;
List<String> l3 = ( List<String> ) l;

Does work. Why is that the case?

Upvotes: 0

Views: 127

Answers (2)

hard coder
hard coder

Reputation: 5705

List<Object> l = new ArrayList<>();
List<String> l2 = l; //no casting works here

It doesn't work because you are assigning List<Object> to List<String> however these are incompatible types;

List<? extends Object> l = new ArrayList<>();
List<String> l2 = ( List<String> ) l;
List<String> l3 = ( List<String> ) l;

This works because, at compile time it checks that List<? extends Object> can be casted to List<String>

When we don't use extends keyword the types are expected to be exact.

Upvotes: 2

Thomas
Thomas

Reputation: 88707

That's because List<? extends Object> might actually refer to a List<String> and thus the compiler has to trust the developer.

In the first case the compiler knows that the cast will mess with the assumptions other code will have (i.e. that you can put every kind of object into l and that l2 will only contain strings) and thus is able to refuse the cast.

The same (or something similar) happens with plain objects:

Integer i = new Integer(1);
String s = (String)i;

The above will fail because the compiler knows that an Integer object can't possibly be cast to String.

However, the following at least compiles since the compiler doesn't know the actual type of i (think of i coming from elsewhere in your code) and thus the compiler has to trust you know what you're doing.

Object i = new Integer(1);
String s = (String)i;

Upvotes: 3

Related Questions