Это упрощенная версия рассматриваемого кода, один универсальный класс использует другой класс с параметрами универсального типа и должен передать один из универсальных типов в метод с параметрами varargs:
class Assembler<X, Y> {
void assemble(X container, Y... args) { ... }
}
class Component<T> {
void useAssembler(T something) {
Assembler<String, T> assembler = new Assembler<String, T>();
//generates warning:
// Type safety : A generic array of T is
// created for a varargs parameter
assembler.assemble("hello", something);
}
}
Есть ли правильный способ передачи универсального параметра в метод varargs без появления этого предупреждения?
Конечно как то
assembler.assemble("hello", new T[] { something });
не работает, так как вы не можете создавать универсальные массивы.
Ответы:
Кроме добавления
@SuppressWarnings("unchecked")
, я так не думаю.Этот отчет об ошибке содержит больше информации, но сводится к тому, что компилятору не нравятся массивы универсальных типов.
источник
Том Хотин указал на это в комментарии, но чтобы быть более точным: да, вы можете решить это на сайте объявлений (а не на (потенциально многих) сайтах вызовов): переключитесь на JDK7.
Как вы можете видеть в блоге Джозефа Дарси, упражнение «Project Coin» для выбора небольших дополнительных улучшений языка для Java 7 приняло предложение Боба Ли разрешить что-то вроде
@SuppressWarnings("varargs")
метода сбрасывало это предупреждение в ситуациях, когда оно было известно сейф.Это было реализовано в OpenJDK с этим коммитом .
Это может или не может быть полезным для вашего проекта (многие люди не будут рады перейти на нестабильную версию JVM, выпущенную до выпуска!), Но, возможно, это так, или, возможно, кто-то, кто найдет этот вопрос позже (после выхода JDK7) ) найдет это полезным.
источник
Если вам нужен свободный интерфейс, вы можете попробовать шаблон сборки. Не такой краткий, как varargs, но он безопасен от типов.
Статический метод общего типа может исключить некоторые из шаблонов при использовании компоновщика, сохраняя при этом безопасность типов.
Строитель
Используй это
источник
Collection
(в данном случае anArrayList
) навязывается вызывающей стороне, тогда как они могут знать, что aLinkedList
более подходит, или сам неизменяемый массив (например, varargs из OP-вопроса). В случае использования без специального назначения это может быть уместно, но просто указав, что это также является ограничением, в зависимости от кода, окружающего это, и ваших потребностей.Явное приведение параметров к Object в вызове метода vararg сделает компилятор счастливым, не прибегая к @SuppressWarnings.
Я считаю, что проблема заключается в том, что компилятор должен выяснить, какой конкретный тип массива создать. Если метод не является универсальным, компилятор может использовать информацию о типе из метода. Если метод является общим, он пытается определить тип массива на основе параметров, используемых при вызове. Если типы параметров являются однородными, эта задача проста. Если они меняются, компилятор пытается быть слишком умным, на мой взгляд, и создает универсальный массив типа union. Тогда он вынужден предупредить вас об этом. Более простым решением было бы создать Object [], когда тип не может быть лучше сужен. Приведенное выше решение заставляет именно это.
Чтобы лучше это понять, поэкспериментируйте с вызовами вышеуказанного метода list по сравнению со следующим методом list2.
источник
Вы можете добавить @SafeVarargs в метод начиная с Java 7, и вам не нужно комментировать клиентский код.
источник
Вы можете перегружать методы. Это не решит вашу проблему, но минимизирует количество предупреждений (и да, это взлом!)
источник
Это очень простая проблема: используйте
List<T>
!Массивы ссылочного типа следует избегать.
В текущей версии Java (1.7) вы можете пометить метод, с помощью
@SafeVargs
которого будет удаляться предупреждение от вызывающей стороны. Осторожней с этим, хотя, и вы все еще лучше без устаревших массивов.См. Также Улучшенные предупреждения и ошибки компилятора при использовании формальных параметров без переопределения с техническими примечаниями Varargs .
источник
При работе с массивами универсального типа я вынужден передавать ссылку на универсальный тип. С этим я могу сделать общий код, используя java.lang.reflect.Array.
http://java.sun.com/javase/6/docs/api/java/lang/reflect/Array.html
источник