Как обеспечить достоверность параметризованных типов до создания экземпляра объекта

Изучая пункт 23 книги Effective Java 2nd Edition, я решил попытаться создать экземпляр объекта с помощью конструктора, который имеет необработанную коллекцию со списком аргументов смешанных объектов. Я предполагал, что компилятор обнаружит, что я пытаюсь передать необработанный тип конструктору. Однако компилятор выдает только предупреждение о непроверенном исключении «у вызывающего, а не у вызываемого».

Класс компилируется нормально, что еще раз подтверждает заявление Джоша Блоха не использовать необработанные типы в новом коде. Тот факт, что это компилируется, меня немного беспокоит.

В? Как можно обеспечить безопасность типов класса до создания экземпляра объекта, за исключением необходимости вручную проверять допустимость объекта в конструкторе? Следующее предоставило только предупреждение о непроверенном назначении от «вызывающего... в основном». Как можно защититься от этого.

public class RawType {

    private final Collection<Example> example;

    public RawType( Collection<Example> example ) {
        this.example = example;
    }

    public Collection<Example> getExample() {
        return example;
    }

    public static void main( String[] args ) {

        Collection unsafe = new ArrayList();

        unsafe.add( new Example() );
        unsafe.add( new Corruption() );
        unsafe.add( new Example() );

        RawType rawType = new RawType( unsafe ); // Corruption

        for(Object type : rawType.getExample()) {
            System.out.println(type.getClass().getName()); // Mixed Classes...
        }

    }

    static class Corruption {}

    static class Example{}

}

person Edward J Beckett    schedule 07.10.2014    source источник
comment
Не игнорируйте предупреждения, чтобы избежать такой ситуации.   -  person Braj    schedule 07.10.2014
comment
Предупреждение не в вызываемом объекте (конструкторе), так как в этом нет ничего плохого. Проблема в вызывающей стороне, где вы используете необработанный тип, где вы должны использовать правильный общий тип. Чтобы предупреждение было также на стороне вызываемого объекта, он должен был бы сказать, что этот конструктор/метод неправильно используется где-то еще, и это просто не имеет смысла.   -  person kajacx    schedule 08.10.2014
comment
Я ясно сказал, Звонящий. В основном Представьте, что вы создаете API, и кто-то отправляет необработанный тип... Как вы можете защитить программу от него без ручной проверки. Вот в чем вопрос.   -  person Edward J Beckett    schedule 08.10.2014
comment
Я не должен беспокоиться об этом. Каждый Java-программист должен знать, что использование необработанных типов осуществляется на его страх и риск, и если его программа из-за этого не работает, это его вина, а не ваша. Также обратите внимание, что подавляющее большинство классов/API также не защищают от необработанных аргументов.   -  person kajacx    schedule 08.10.2014
comment
Многие API также не защищают от необработанных аргументов... Никогда не думал об этом... интересно.   -  person Edward J Beckett    schedule 06.12.2014


Ответы (2)


Строки ниже компилируются, но также генерируют предупреждения.

Collection unsafe = new ArrayList(); // RAW type
unsafe.add(1);                       // no compile time error (just warning)

Collection<String> example = unsafe; // assign RAW type to parametrized type
example.add(1);                      // compile time error

Лучше использовать общую коллекцию, чтобы избежать такой ситуации, а затем добавить в нее значения. Никогда не смешивайте RAW с параметризованным тип.


Посмотрите на код ниже:

Collection<Integer> unsafe = new ArrayList<Integer>();
unsafe.add(1);
Collection<String> example = unsafe; // compile time error

Подробнее...


Если вы не можете избежать типа RAW, используйте следующий код в конструкторе:

Collection unsafe = new ArrayList(); 
unsafe.add(1);                       
unsafe.add("hello");

// in the constructor, just add String values from the unsafe collection
Collection<String> example = new ArrayList<String>(); 
for(Object value:unsafe){
    if(value instanceof String){
        example.add((String)value);
    }
}
person Braj    schedule 07.10.2014
comment
Я пытаюсь понять, как я могу гарантировать, что «вызывающий» не отправит чужой тип в аргументе? Кажется, невозможно добиться соответствия без реализации валидации. - person Edward J Beckett; 07.10.2014
comment
Почему вы используете тип RAW? можно ли этого избежать? - person Braj; 07.10.2014
comment
Generic работает только для проверки времени компиляции. Вся информация об универсальном типе теряется во время выполнения. - person Braj; 07.10.2014
comment
Да, это не производство... это обзор Пункт 23 Эффективная Java Не используйте необработанные типы... - person Edward J Beckett; 07.10.2014

Чтобы сделать java-дженерики совместимыми с кодом, написанным до их появления, вы можете использовать нетипизированную коллекцию везде, где ожидается типизированная коллекция. Таким образом, коллекция (без параметра типа) может быть передана конструктору, который ожидает коллекцию.

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

person PaulJWilliams    schedule 07.10.2014