Избегайте создания общих классов с помощью непроверенных приведений типов

Допустим, я создаю пакет process с публичным классом Processor, который имеет конструктор, который ожидает параметр типа Container<I>, Класс Container<I> лежит в другом пакете вне моего контроля и содержит объекты произвольного типа I, Контейнер с содержащимися элементами передается между несколькими классами пакета process,

Элементы обрабатываются с помощью методов интерфейса Processable, Они могут быть получены пользователем process через метод getProcessedItem(Property property), Этот метод возвращает обработанный элемент со свойством property который гарантированно содержится в переданном контейнере и поэтому может быть приведен к параметру типа контейнера.

пример класса:

package process;

import container.Container;

public class Processor<I extends Processable> {
    private final ItemProcessor itemProcessor;

    public Processor(Container<I> container){       
        this.itemProcessor = new ItemProcessor(container);
    }

    @SuppressWarnings("unchecked")
    public I getProcessedItem(Property property){
        return (I)itemProcessor.getProcessedItem(property);
    }

}

Как правило, в такой ситуации неплохо создавать неконтролируемое приведение типов?

Единственная разумная альтернатива, которую я до сих пор выяснил, - сделать все классы в пакете process которые должны содержать ссылку на параметризованный контейнер (например, ItemProcessor) также является общим для сохранения информации о типе, необходимой для getProcessedItem(Property property),

РЕДАКТИРОВАТЬ: Чтобы уточнить функциональность класса контейнера в моем примере:

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

Это означает ItemProcessor и классы, используемые ItemProcessor должен иметь возможность обрабатывать обрабатываемые элементы (после их извлечения из контейнера) так, как им нравится (например, сохранять их в списках или других структурах данных). И, наконец, должна быть возможность запрашивать обработанный элемент на основе определенного свойства процессора. Например:

getProcessedItem(Property.MOST_RECENTLY_PROCESSED)

Как стандартные классы коллекции Java (например, ArrayList) Container<I> не гарантирует строго, что он содержит только I и его потомки. Это означает, что когда-то контейнер используется как Processableв то время как на самом деле не будучи Processableпроисходит исключение приведения.

В приведенной выше версии класса Processor исключение не генерируется сразу, когда элемент запрашивается через getProcessedItem не совместим с типом I (из-за непроверенного актерского состава). Но также, если я сделал ItemProcessor общий (ItemProcessor<I>) и сделал свое getProcessedItem return I вместо использования непроверенного приведения, в этот момент не будет выброшено исключение. Поэтому я также не уверен, что было бы лучше сделать проверку типа во время выполнения, используя Class<I> объект в getProcessedItem, Class<I> объект должен явно обслуживаться вызывающей стороной как параметр или через заданный контейнер. Я чувствую, что процессор не должен заботиться о том, чтобы элементы в контейнере действительно были совместимы с Iпотому что процессор не несет ответственности за достоверность содержимого данного контейнера.

2 ответа

Class класс имеет cast() метод, который не генерирует никаких предупреждений...

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

Я думаю, что ваши SuppressWarnings побеждает цель дженериков. Что вам нужно сделать, так это сделать элемент getProcessed общим.

public class ItemProcessor<I extends Processable> {
    public I getProcessedItem() {
       return somethingWhichIsProcessable;
    }
Другие вопросы по тегам