Каковы последствия преобразования универсального списка в неуниверсальный список? - PullRequest
1 голос
/ 11 марта 2010

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

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

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

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

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

РЕДАКТИРОВАТЬ: Фрагмент кода является подробным, чтобы явно продемонстрировать то, что я описываю ..

Ответы [ 5 ]

3 голосов
/ 11 марта 2010

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

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

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

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

request.setAttribute("listThings", listFoo);

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

2 голосов
/ 11 марта 2010

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

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

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

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

1 голос
/ 11 марта 2010

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

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

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

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

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

0 голосов
/ 11 марта 2010

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

0 голосов
/ 11 марта 2010

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

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

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

...