2010-03-11 1 views
1

Я рефинансирую домашний контейнер DAO, надеясь сделать класс универсальным. Он внутренне использует ArrayList для хранения извлеченных объектов.Каковы последствия приведения общего списка в не общий список?

Одно использование этого класса помещает список контейнера в область запроса, и из-за ограничения Websphere я не могу передать общий размер List<Foo> в область запроса (Websphere не обрабатывает генерические данные вне -Box)

Если я иду вперед с моим рефакторингом, мне нужно будет конвертировать/кастовали List<Foo> в необщий List объект ..

// Boils down to this... 
List<Foo> listFoo = new FooListing().findAllFoo(); 
List listThings = listFoo; 
request.setAttribute("listThings", listThings); 

Каковы последствия реверсирования родового, как это ? Должен ли я избегать подобных манипуляций?

EDIT: Фрагмент код многословный явно демонстрирует то, что я описываю ..

+0

Вам не нужно промежуточное присвоение listThings; вы можете просто установить listFoo прямо в запрос. –

ответ

3

Если тип компонента списка не соответствует ожидаемому типу, нет никаких проблем.

Дженерики в Java используются только для проверки типов компилятором, они не влияют на время выполнения. Если вы используете более старую библиотеку, которая не поддерживает дженерики, у вас нет выбора, кроме как игнорировать общий тип. Все должно продолжаться, поскольку эта система была разработана с учетом обратной совместимости.

Итак, все, что вы теряете, это проверка типа компиляции (она вернет вас туда, где Java была в 1,4, что означает, что если типы совпадают, все будет работать, если нет, вы получите ClassCastExceptions или другое нежелательное поведение во время выполнения).

Однако, я думаю, вы можете просто написать

request.setAttribute("listThings", listFoo); 

Этот метод принимает объект любого типа. Даже если ему нужен Список, вы все равно можете передать List<Foo> (который по-прежнему является списком).

+0

Прохладный, просто хотел явно продемонстрировать, что я описывал в примере кода – brasskazoo

+0

Вы можете передать свой «Список » всем методам, которым нужен не общий список. WebSphere не может вмешиваться в это. Так работает обратная совместимость. – Thilo

0

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

Во-вторых, два основных преимущества общего списка: 1) он гарантирует, что все объекты имеют указанный тип, и 2) он позволяет вам напрямую обращаться к методам коллекции объектов, не переделывая их. Это позволяет вам писать более чистый код и экономить некоторые циклы обработки от необходимости отбрасывать назад и четвертый.

Однако ни одно из этих преимуществ не является крайней необходимостью. Если вы не можете их использовать, вы не заметите разницы в производительности. Однако ваш код может выглядеть немного грязнее.

+1

Вы абсолютно можете использовать общий список для не общего. Возможно, вам придется подавить предупреждение, но вы абсолютно можете это сделать. Это имеет смысл, поскольку после стирания они точно такие же. – polygenelubricants

+0

«вы не можете использовать общий родословный список». Вы можете написать 'List x = (List) listFoo'. – Thilo

+0

Ах, мой плохой. Должно быть, я думал: «Вы не можете отнести один общий список в другой общий список» и получили это в голове. –

2

Java использует «тип стирания» для генериков -. По существу это означает, что компилятор проверяет дженерики, но во время выполнения забывает об этом и просто рассматривает его как список объектов *

Всякий раз, когда вы лечить List<Foo> как просто список, вы не получите проверки компилятора, чтобы убедиться, что вы не поместили Bla в свой список. Таким образом, вы можете получить ClassCastException, если вы вызываете List<Foo>.get(), и это оказывается Bla, скрывающимся в списке. Но это может произойти только в том случае, если какой-либо код помещает Bla в ваш список.

Если вы не будете осторожны, то если вы передадите List<Foo> в качестве списка на все, что могло бы добавить не-Foo в список, не обращайтесь с ним как List<Foo> всякий раз, когда вы обращаетесь к нему, но лечите это как список Objects и добавить проверки экземпляров.

* Некоторая информация доступна во время выполнения, но давайте не будем усложнять ситуацию.

+0

К счастью, использование списка в этом случае предназначено только для показа, поэтому нет риска взрыва bla на наших лицах – brasskazoo

0

У меня есть аналогичные проблемы с Weblogic Portal. Просто используйте для этого случая не-общий тип.

1

«Неоригинальная» версия родового типа называется «сырым типом».

Передача типового типа, в котором запрашивается необработанный эквивалент, в общем случае. На самом деле это основная причина, по которой дженерики в Java работают так, как они делают (с стиранием): чтобы обеспечить взаимодействие между «генерализованным» кодом и кодом pre-generics.

Главное, что вам нужно быть осторожным в том, что если вы передаете List<Foo> к чему-то, что askes для List, они могут поместить Непро- Foo объекты в List. Вы не получите никакой проверки времени компиляции, чтобы помочь вам здесь. Вы do получите несколько проверок времени выполнения: ClassCastException будет выброшен при использовании метода, который возвращает Foo на вашем List<Foo>, и он должен вернуть не Foo.

Если вы хотите более быстрого поиска, вы можете обернуть List<Foo>Collections.checkedList(), чтобы получить список, который будет проверять тип элементов при вставке.

Все сложнее, если Foo сам по себе является общим типом. Проверки времени выполнения выполняются только для типов reified (т. Е. Тип с типичными параметрами типа), поэтому, если вы даете им List<Set<Bar>>, и они вставляют Set<Baz> или просто Set, вы не будете знать, так как тип времени выполнения/reified Set в любом случае.