| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > Java: Общие вопросы > Generics |
| Автор: Alexey91 29.9.2013, 12:03 |
| Здравствуйте! Contaiter <Object> obj = new Contaiter <String>(); Почему это вызывает ошибку? Я понимаю, что так нельзя и так не делаю, но не могу объяснить почему Contaiter <String> obj = new Contaiter <Obj>(); в этом случае мне понятно, поскольку в коде могут использоваться методы класса String а у Object этих методов нет, поэтому возникте ошибка... Почему нельзя в первом случае? |
| Автор: Stolzen 29.9.2013, 13:23 | ||||
| Потому что генерики в джаве не ковариантны, т.е. List<Object> не является суперклассом для List<String>. Добавлено через 7 минут и 7 секунд Для чего так сделано, можно почитать в Effective Java item 25. Если вкратце, то массивы ковариантны (String[] является подклассом Object[]) и поэтому можно сделать так:
А со списками такое не прокатит:
|
| Автор: Samotnik 29.9.2013, 13:33 | ||
Давай разберем
1. Contaiter <Object> obj в этом случае, Object - это аргумент, определяющий тип, который передается параметру E (или какой ты используешь в Container?). Это значит, что все ссылки, на тип Е будут преобразованы в ссылки на тип Object. Ты можешь посмотреть в IDE, не смотря на ошибку компиляции, если ты напишешь obj. увидишь, что все методы ожидают Object тип. 2. obj = new Contaiter <String>(); тут obj присваивается ссылка на экземпляр версии String класса. Но это неправильно, т.к. у объекта obj, которому присваивается ссылка, уже определен тип <Object>. Это зашито в сам компилятор, он требует, что бы ссылка, возвращаемая операцией new, указывала на тот тип, что был объявлен сразу, если это не соблюдается выдается ошибка. Твое понимание второй ситуации неправильное. Методы то всегда есть, это же не наследование, а настраиваемые типы. Например, всегда будет метод add() только вопрос с чем он будет работать. Во втором случае обоснование такое же, как и для первого. Итого: Тип задается сразу и он должен использоваться и после операции new. Это сделано для безопасности, если ты напишешь Contaiter <Object> obj = new Contaiter <String>(); То с чем ты будешь работать? |