I certainly don't see why
List<Sub> list;
public Iterator<Super> iterator() {
return (Iterator<Super>)sections.iterator();
}
wouldn't cast.
Consider situation where you have classes Fruit
Apple
Banana
. You have list of Fruit
s
List<Fruit> list = new ArrayList<>();
so you can add to it any kind of fruit like Apple
or Banana
.
list.add(new Apple());
list.add(new Banana());
Now would it be safe to cast such list to more specified type, lets say list of Apple
s? No. Why? Consider following example:
List<Apple> apples = (List<Apple>)list; //lets assume for now that this is OK
for (Apple ap : apples){
//do something with apple
}
But list
contains not only Apple
s but also Banana
, which is not right argument for code in for
loop.
You to solve this problem in many ways, for instance you can try using wildcards like List<? extends Super>
. It all depends on what you are actually trying to achieve.
Response to your update
List<Sub> list;
public Iterator<Super> iterator() {
Iterator<? extends Super> iterator = ((List<? extends Super>)list).iterator();
return (Iterator<Super>)iterator;
}
Is same as
public Iterator<Super> iterator() {
List<? extends Super> tmp = list; //1
Iterator<? extends Super> iterator = tmp.iterator(); //2
return (Iterator<Super>) iterator; //3
}
In line marked //1
you are creating temporary reference of type List<? extends Super>
and use it to handle list
which is type List<Sub>
which is perfectly fine, because <? extends Super>
was meant to hold type which extends Super
like in this case Sub
.
In line //2
you are creating iterator using tmp
reference so you are getting iterator with same generic type as this reference so it is Iterator<? extends Super>
.
Now problem can happen here
return (Iterator<Super>) iterator; //3
Consider situation:
You have List<? extends Super>
and you want to cast it to List<Super>
. Would that be safe? Not really, because via List<Super>
you would be able to add any instance of Super
type and its subtypes, like SubFoo
or SubBar
. It means that if List<? extends Super>
would hold List<SubBar>
you would be able to add to this list not only desired SubBar
but also SubFoo
, which is potentially dangerous. That is why compiler will inform you about potential danger.
Interestingly this time you will not see compilation error, but warning. It is probably because explicitly casting List<Sub>
to List<Super>
is to big shortcut which could lead to misunderstandings because programmers could forget what wrong could happen.
Using casting from wildcard may demonstrate that you understand generics enough to say "OK compiler, I am aware of possible problems you want to protect me from, but I know what I am doing", that is why you are seeing warning instead of compilation error.