Это:
myList.add(new FileNotFoundException());
компилируется, потому что FileNotFoundException
равно IOException
, так же как равно * Exception
, поэтому оно удовлетворяетграница myList
.
This:
myList.add(new Exception());
делает не компиляцией, потому что компилятор не знает, какой точный тип список(он не проверяет, что было назначено для varaible, он только смотрит на его объявленный тип), поэтому он не знает, имеет ли назначенный ему список тип, который соответствует супертипу IOException
, но не Exception
.
Это может произойти, если в иерархии между Exception
и IOException
существует промежуточный класс.Если список действительно имел этот тип, Exception
может не совпадать с границей фактического списка, назначенного для myList
.
Компилятор не проверяет ни полную иерархию классов, ни то, что было назначено.Он выполняет только базовую проверку, которая всегда позволяет избежать ошибок во время выполнения.
Это также верно в более общем случае, когда «логически» нет пути к коду, который может вызвать ошибку, но компиляция все равно не удалась.