Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Lower bound generic in java does not compile even when passing super class

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
like image 990
Sumit Avatar asked Jan 02 '23 00:01

Sumit


2 Answers

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 IOExceptions, 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.

like image 176
rgettman Avatar answered Jan 08 '23 02:01

rgettman


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.

like image 44
Bohemian Avatar answered Jan 08 '23 02:01

Bohemian