Я хотел бы реализовать функцию с обоими дженериками и 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>, Класс <?>... классы)" и избавиться от предупреждений, но это также удаляет тип времени компиляции, проверяющий---не настолько хороший, если я хотел гарантировать правильное использование в этой функции. Какое-либо лучшее решение?
Как почти всегда, Анжелика Лангер в FAQ по дженерикам Java объясняет это очень подробно . (Прокрутите до «Почему компилятор иногда выдает непроверенное предупреждение, когда я вызываю метод« varargs »?» - идентификатор работает некорректно.)
По сути, вы теряете информацию хуже, чем обычно. Еще одна маленькая проблема в дженериках Java: (
Ответ Джона Скита (конечно) правильный; Я немного расскажу об этом, указав, что вы МОЖЕТЕ избавиться от этого предупреждения с помощью большого «если». Вы можете избежать этого предупреждения, ЕСЛИ вы готовы выполнить сборку своего проекта с использованием Java 7.
Боб Ли написал предложение , чтобы позволить подавить это предупреждение на сайте объявления метода, а не использовать сайт, как часть Project Coin .
Это предложение было принято для JDK7 (хотя синтаксис немного изменился, на @SuppressWarnings ("varargs")
); Если вам интересно, вы можете посмотреть коммит, добавивший эту поддержку в JDK .
Не обязательно полезно для вас, но я подумал, что сделаю это отдельным ответом, чтобы он продолжал жить для будущих читателей, которым, возможно, посчастливится жить в мире после Java-7.
Хорошо, в конце концов я выбрасываю 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);
}
}
Единственный недостаток - это длинный код для заполнения коллекции, используемой для переноса аргументов функции.
Второй аргумент Class extends A>
... который должен расширять класс, которым является первый аргумент (например, первый аргумент - это вопрос
, поэтому второй аргумент является чем-то, что расширяет вопрос
.
Разбор:
NastyThingsToClasses (Object.class, Question.class, SomeQuestion.class); // ОК
Все расширяется Object
, поэтому второй аргумент верен.
NastyThingsToClasses ( Question.class, SomeQuestion.class); // ОК
SomeQuestion
расширяет Question
, так что это честная игра.
NastyThingsToClasses (Question.class, Object.class, SomeQuestion.class);
Объект
не расширяет Вопрос
, следовательно, ошибка.
Надеюсь, это прояснило ситуацию.
-Brett