Подстановочный знак с верхней границей в Java Generics - PullRequest
5 голосов
/ 21 марта 2011

после того, как я искал некоторое время, я все еще не мог найти ответ на свой вопрос, даже если есть пара тем, связанных с Обобщением, так что здесь вы идете:

ArrayList<? super IOException> list = new ArrayList<Exception>();
list.add(new FileNotFoundException("this is ok."));
list.add(new IOException("This is ok"));
list.add(new ClassCastException("compile err"));//why compile err?
list.add(new Exception("compile err"));//why compile err? 

Почему две последние строки не компилируются? Особенно последняя строчка. Я довольно много тестировал эту тему, но все еще не мог понять логику.

Спасибо.

Ответы [ 6 ]

8 голосов
/ 21 марта 2011

ArrayList<? super IOException> может быть любым из следующих (так как здесь подстановочный знак):

ArrayList<IOException>
ArrayList<Exception>
ArrayList<Throwable>
ArrayList<Object>

Код должен работать со всеми четырьмя возможностями.

Но если это такArrayList<IOException>, вы не можете вставить ClassCastException или Exception, следовательно, ошибки компиляции.

Вот что я не получаю: почему эта компиляция ------ >>> list.add (new FileNotFoundException ("это нормально."));<<< ---- Я думаю, FileNotFoundException также ниже границы IOException.но компилируется нормально.</p>

Нет, FileNotFoundException - это нормально, поскольку он расширяет IOException, и вы можете поместить его во все четыре типа списков.

Обратите внимание, что по историческим причинам массивы не получаютПри такой же строгой проверке типов вы можете скомпилировать следующее (а затем получить исключение хранилища массивов во время выполнения):

   Exception[] a = new IOException[4];
   a[0] = new FileNotFoundException("this is ok.");  
   a[1] = new IOException("This is ok");
   a[2] = new ClassCastException("compiles, but boom!");
   a[3] = new Exception("compiles, but boom!"); 
4 голосов
/ 21 марта 2011

Рассмотрим то же объявление list, но с другим назначением:

ArrayList<? super IOException> list = new ArrayList<IOException>();

Нет изменений в типе list, но теперь добавление ClassCastException или Exception явно неверно.

1 голос
/ 18 декабря 2013

Для меня это относится к подстановочным знакам: <? super IOException>.Подстановочные знаки с ограничением сверху будут иметь значение <? extends IOException>.

Подстановочный знак в вашем примере кажется эффективным только в той строке, в которой новая Object назначена переменной.При последующем доступе это, очевидно, уже не эффективно.Тогда это то же самое, что и ArrayList<IOException>.

Так что ваше объяснение для себя, по-видимому, неверно.Верхний и нижний ограниченный означает, что он говорит.

1 голос
/ 21 марта 2011

Exception является суперклассом, поскольку IOException расширяется Exception.Вы можете использовать:

 List<Exception> list = new ArrayList<Exception>();
 list.add(...); // any exception

Тогда он скомпилируется для всех типов исключений.

0 голосов
/ 21 марта 2011

В соответствии с вашим общим обобщенным объявлением ArrayList, вы можете добавить только фактическое IOException (из-за? Super) или объекты, которые расширяют IOException, в список.

ClassCaseException и Exception не являются производными от IOException, поэтому происходит сбой.

0 голосов
/ 21 марта 2011

я думаю, потому что последние исключения не являются производными от базового класса IOException

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...