x***n 发帖数: 70 | 1 请问下面一段代码中,为什么第8行处能compile通过而第14行不行?
我的理解是,exceptions 事实上是List (因此所有Exception的子类都可
以包含),而numbers事实上就是List,那么14行也理应可以通过才对?
1 ArrayList < ? super IOException > exceptions =
2 new ArrayList < Exception > ();
3 IOException e1 = new IOException("Problem 1");
4 IOException e2 = new IOException("Problem 2");
5 FileNotFoundException e3 = new FileNotFoundException("Problem 3");
6 exceptions.add(e1);
7 exceptions.add(e2);
8 exceptions.add(e3);
9 System.out.println(exceptions);
10
11 List super Integer> numbers = new ArrayList ();
12 numbers.add(232);
13 Number n = new Integer(2);
14 numbers.add(n); //can't compile
非常感谢! | r*****l 发帖数: 2859 | 2 This is kinda tricky.
The compile just looks at the declaration to determine the type.
In the IOException example, you know the list can hold "a type" that is IOException's parent class (the exact type is not known). It's ok to add FileNotFoundException since FileNotFoundException is IOException's child, and for sure FileNotFoundException is IOException's parent's child. Without knowing what "a type" is, it's guaranteed that FileNotFoundException is safe to put in the list.
In the Number example, for the same reason, you can add Integer and all its child types to the list (Integer cannot have a child type since it's final). You cannot add any of Integer's parent. Because the compiler just knows the list can hold "a type" that is Integer's parent (or itself), but if you put one of Integer's parent, without knowing what "a type" is, the compiler cannot guarantee that "a type" is compatible with the type you are going to add.
【在 x***n 的大作中提到】 : 请问下面一段代码中,为什么第8行处能compile通过而第14行不行? : 我的理解是,exceptions 事实上是List (因此所有Exception的子类都可 : 以包含),而numbers事实上就是List,那么14行也理应可以通过才对? : 1 ArrayList < ? super IOException > exceptions = : 2 new ArrayList < Exception > (); : 3 IOException e1 = new IOException("Problem 1"); : 4 IOException e2 = new IOException("Problem 2"); : 5 FileNotFoundException e3 = new FileNotFoundException("Problem 3"); : 6 exceptions.add(e1); : 7 exceptions.add(e2);
| x***n 发帖数: 70 | 3 Many thanks!
So the key is "compiler just looks at the declaration to determine the type"
, and the compiler needs to make sure the element to be added is of the type
surely safe to be added.
So I think that's the same reason why 3 and 4 in the following statements
can't compile:
1 List< ? extends Number> list1 = new ArrayList ();
2 List< ? > list2 = new ArrayList ();
3 list1.add(3.2);
4 list2.add(4.8);
IOException's parent class (the exact type is not known). It's ok to add
FileNotFoundException since FileNotFoundException is IOException's child,
and for sure FileNotFoundException is IOException's parent's child. Without
knowing what "a type" is, it's guaranteed that FileNotFoundException is safe
to put in the list.
its child types to the list (Integer cannot have a child type since it's
final). You cannot add any of Integer's parent. Because the compiler just
knows the list can hold "a type" that is Integer's parent (or itself), but
if you put one of Integer's parent, without knowing what "a type" is, the
compiler cannot guarantee that "a type" is compatible with the type you are
going to add.
【在 r*****l 的大作中提到】 : This is kinda tricky. : The compile just looks at the declaration to determine the type. : In the IOException example, you know the list can hold "a type" that is IOException's parent class (the exact type is not known). It's ok to add FileNotFoundException since FileNotFoundException is IOException's child, and for sure FileNotFoundException is IOException's parent's child. Without knowing what "a type" is, it's guaranteed that FileNotFoundException is safe to put in the list. : In the Number example, for the same reason, you can add Integer and all its child types to the list (Integer cannot have a child type since it's final). You cannot add any of Integer's parent. Because the compiler just knows the list can hold "a type" that is Integer's parent (or itself), but if you put one of Integer's parent, without knowing what "a type" is, the compiler cannot guarantee that "a type" is compatible with the type you are going to add.
| r*****l 发帖数: 2859 | 4 Right. If you change "extends Number" to "super Number", then line 3 will
compile.
You can do something like this:
List extends Number> l1;
List l2 = new ArrayList;
l1 = l2;
l2.add(3.4);
type"
type
【在 x***n 的大作中提到】 : Many thanks! : So the key is "compiler just looks at the declaration to determine the type" : , and the compiler needs to make sure the element to be added is of the type : surely safe to be added. : So I think that's the same reason why 3 and 4 in the following statements : can't compile: : 1 List< ? extends Number> list1 = new ArrayList (); : 2 List< ? > list2 = new ArrayList (); : 3 list1.add(3.2); : 4 list2.add(4.8);
| x***n 发帖数: 70 | 5 Thanks. I see your point. l1 is used as a "readonly" view of l2.
【在 r*****l 的大作中提到】 : Right. If you change "extends Number" to "super Number", then line 3 will : compile. : You can do something like this: : List extends Number> l1; : List l2 = new ArrayList; : l1 = l2; : l2.add(3.4); : : type" : type
| r*****l 发帖数: 2859 | 6 You have good sense. Actually most of the time > and extends ...> are
for read only use, although you can add null to the collection.
【在 x***n 的大作中提到】 : Thanks. I see your point. l1 is used as a "readonly" view of l2.
| B*****g 发帖数: 34098 | 7 基础不扎实,看着有点晕
【在 r*****l 的大作中提到】 : You have good sense. Actually most of the time > and extends ...> are : for read only use, although you can add null to the collection.
| x***n 发帖数: 70 | 8 I see. Many thanks!
【在 r*****l 的大作中提到】 : You have good sense. Actually most of the time > and extends ...> are : for read only use, although you can add null to the collection.
|
|