Дженерики Java и varargs

Я хотел бы реализовать функцию с обоими дженериками и varargs.

public class Question {
    public static <A> void doNastyThingsToClasses(Class<A> parent, Class<? extends A>... classes) {
        /*** something here ***/
    }
    public static class NotQuestion {
    }
    public static class SomeQuestion extends Question {
    }
    public static void main(String[] args) {
        doNastyThingsToClasses(Object.class, Question.class, SomeQuestion.class); // OK
        doNastyThingsToClasses(Question.class, SomeQuestion.class); // OK
        doNastyThingsToClasses(Question.class, Object.class, SomeQuestion.class); // compilation failure
    }
}

Намерение здесь состоит в том, чтобы утверждать, что всеми параметрами, переданными этой функции, являются Объекты класса, расширяющие Класс, данный как первый параметр. Таким образом, две первых строки основного метода скомпилировали бы, и 3-й генерирует ошибку.

Мой вопрос: Почему я получаю "Безопасность с точки зрения типов: универсальный массив Класса создается для varargs параметра" сообщение для первых двух строк?

Я пропускаю что-то здесь?

Дополнительный вопрос: как перепроектировать его для препятствования этому предупреждению быть показанным на каждой строке, вызвав "doNastyThingsToClasses" функцию? Я могу изменить его на "doNastyThingsToClasses (родитель Класса <A>, Класс <?>... классы)" и избавиться от предупреждений, но это также удаляет тип времени компиляции, проверяющий---не настолько хороший, если я хотел гарантировать правильное использование в этой функции. Какое-либо лучшее решение?

32
задан Mike Nakis 15 May 2015 в 20:03
поделиться

4 ответа

Как почти всегда, Анжелика Лангер в FAQ по дженерикам Java объясняет это очень подробно . (Прокрутите до «Почему компилятор иногда выдает непроверенное предупреждение, когда я вызываю метод« varargs »?» - идентификатор работает некорректно.)

По сути, вы теряете информацию хуже, чем обычно. Еще одна маленькая проблема в дженериках Java: (

38
ответ дан 27 November 2019 в 20:27
поделиться

Ответ Джона Скита (конечно) правильный; Я немного расскажу об этом, указав, что вы МОЖЕТЕ избавиться от этого предупреждения с помощью большого «если». Вы можете избежать этого предупреждения, ЕСЛИ вы готовы выполнить сборку своего проекта с использованием Java 7.

Боб Ли написал предложение , чтобы позволить подавить это предупреждение на сайте объявления метода, а не использовать сайт, как часть Project Coin .

Это предложение было принято для JDK7 (хотя синтаксис немного изменился, на @SuppressWarnings ("varargs") ); Если вам интересно, вы можете посмотреть коммит, добавивший эту поддержку в JDK .

Не обязательно полезно для вас, но я подумал, что сделаю это отдельным ответом, чтобы он продолжал жить для будущих читателей, которым, возможно, посчастливится жить в мире после Java-7.

13
ответ дан 27 November 2019 в 20:27
поделиться

Хорошо, в конце концов я выбрасываю varargs:

public class Question {

    public static <A, C extends A> void doNastyThingsToClasses(Class<A> parent, List<Class<? extends A>> classes) {
        /******/
        for(Class<? extends A> clazz : classes) {
            System.out.println(clazz);
        }
    }

    public static class NotQuestion {
    }
    public static class SomeQuestion extends Question {
    }

    public static void main(String[] args) {

        ArrayList<Class<? extends Object>> classes = new ArrayList<Class<? extends Object>>();
        classes.add(Question.class);
        classes.add(SomeQuestion.class);
        classes.add(NotQuestion.class);
        doNastyThingsToClasses(Object.class, classes);

        ArrayList<Class<? extends Question>> clazzes = new ArrayList<Class<? extends Question>>();
        clazzes.add(Question.class);
        clazzes.add(SomeQuestion.class);
        clazzes.add(NotQuestion.class); // yes, this will _not_ compile
        doNastyThingsToClasses(Question.class, clazzes);

    }

}

Единственный недостаток - это длинный код для заполнения коллекции, используемой для переноса аргументов функции.

1
ответ дан 27 November 2019 в 20:27
поделиться

Второй аргумент Class ... который должен расширять класс, которым является первый аргумент (например, первый аргумент - это вопрос , поэтому второй аргумент является чем-то, что расширяет вопрос .

Разбор:
NastyThingsToClasses (Object.class, Question.class, SomeQuestion.class); // ОК
Все расширяется Object , поэтому второй аргумент верен.

NastyThingsToClasses ( Question.class, SomeQuestion.class); // ОК
SomeQuestion расширяет Question , так что это честная игра.

NastyThingsToClasses (Question.class, Object.class, SomeQuestion.class);
Объект не расширяет Вопрос , следовательно, ошибка.


Надеюсь, это прояснило ситуацию.

-Brett

0
ответ дан 27 November 2019 в 20:27
поделиться
Другие вопросы по тегам:

Похожие вопросы: