Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
101 views
in Technique[技术] by (71.8m points)

java - Why is List<Number> not a sub-type of List<Object>?

public void wahey(List<Object> list) {}

wahey(new LinkedList<Number>());

The call to the method will not type-check. I can't even cast the parameter as follows:

wahey((List<Object>) new LinkedList<Number>());

From my research, I have gathered that the reason for not allowing this is type-safety. If we were allowed to do the above, then we could have the following:

List<Double> ld;
wahey(ld);

Inside the method wahey, we could add some Strings to the input list (as the parameter maintains a List<Object> reference). Now, after the method call, ld refers to a list with a type List<Double>, but the actual list contains some String objects!

This seems different to the normal way Java works without generics. For instance:

Object o;
Double d;
String s;

o = s;
d = (Double) o;

What we are doing here is essentially the same thing, except this will pass compile-time checks and only fail at run-time. The version with Lists won't compile.

This leads me to believe this is purely a design decision with regards to the type restrictions on generics. I was hoping to get some comments on this decision?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

What you are doing in the "without generics" example is a cast, which makes it clear that you are doing something type-unsafe. The equivalent with generics would be:

Object o;
List<Double> d;
String s;

o = s;
d.add((Double) o);

Which behaves the same way (compiles, but fails at runtime). The reason for not allowing the behavior you're asking about is because it would allow implicit type-unsafe actions, which are much harder to notice in code. For example:

public void Foo(List<Object> list, Object obj) {
  list.add(obj);
}

This looks perfectly fine and type-safe until you call it like this:

List<Double> list_d;
String s;

Foo(list_d, s);

Which also looks type-safe, because you as the caller don't necessarily know what Foo is going to do with its parameters.

So in that case you have two seemingly type-safe bits of code, which together end up being type-unsafe. That's bad, because it's hidden and therefore hard to avoid and harder to debug.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

2.1m questions

2.1m answers

60 comments

57.0k users

...