List<? super IOException>
means the list can contain IOException
objects or any object that is super
class of IOException
. Then why the below Line 2 does not compile?
Also in Line 3 FileNotFoundException
is not a super
class of IOException
. Then why it compiles?
List<? super IOException> myList = new ArrayList<Exception>();
myList.add(new Exception()); //Line 2 This line do not compile
myList.add(new FileNotFoundException()); //Line 3 This compiles
The wildcard lower bound specifies a lower bound for the type argument, not for the acceptable types of the List
. The type argument could be something as specific as IOException
, but it could be as general as we can get: Object
.
When adding an Exception
, the type of the item is too general as an item, because the type parameter may be too specific for it -- it could be IOException
. The compiler won't allow you to add an Exception
to something that may take only IOException
s, so it generates the error.
This doesn't occur with FileNotFoundException
, because no matter how specific the type parameter is, it won't be any more specific than IOException
(the lower bound), so a FileNotFoundException
, which is a subclass of IOException
, is legal in all cases, so the compiler allows it.
This:
myList.add(new FileNotFoundException());
compiles because FileNotFoundException
is an IOException
, just as it is an Exception
, so it satisfies the bound of myList
.
This:
myList.add(new Exception());
does not compile because the compiler does not know what exact type the list is (it doesn't check what was assigned to the varaible, it only looks at its declared type), so it doesn't know if the list assigned to it has a type that matches a super type of IOException
, but not Exception
.
This would happen is there was an intermediate class in the hierarchy between Exception
and IOException
. If the list actually had that type, Exception
may not match the bound of the actual list assigned to myList
.
The compiler doesn't check the complete class hierarchy nor what was assigned. It only does a basic check that always avoids runtime errors.
This is also true more generally where "logically" there is no code path that will cause an error, but the compile still fails.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With