Я понимаю, что это происходит с Java 7 при использовании varargs с универсальным типом;
Но мой вопрос ..
Что именно означает «Затмение», когда говорит, что «его использование может привести к загрязнению кучи?»
А также
Как новая @SafeVarargs
аннотация предотвращает это?
java
eclipse
generics
variadic-functions
Герцшпрунга
источник
источник
Possible heap pollution from parameterized vararg type
Ответы:
Загрязнение кучи - это технический термин. Это относится к ссылкам, которые имеют тип, который не является супертипом объекта, на который они указывают.
Это может привести к "необъяснимым"
ClassCastException
с.@SafeVarargs
не мешает этому вообще. Однако есть методы, которые доказуемо не будут загрязнять кучу, компилятор просто не может этого доказать. Раньше вызывающие такие API получали раздражающие предупреждения, которые были совершенно бессмысленными, но их нужно было подавлять на каждом сайте вызовов. Теперь автор API может отключить его один раз на сайте декларации.Однако, если метод на самом деле не безопасно, пользователи больше не будут предупреждены.
источник
Когда вы объявляете
public static <T> void foo(List<T>... bar)
компилятор преобразует его вpublic static <T> void foo(List<T>[] bar)
затем кpublic static void foo(List[] bar)
Тогда возникает опасность, что вы ошибочно назначите неверные значения в список, и компилятор не вызовет никаких ошибок. Например, если
T
is,String
то следующий код скомпилируется без ошибок, но завершится с ошибкой во время выполнения:Если вы проверили метод, чтобы убедиться, что он не содержит таких уязвимостей, вы можете аннотировать его,
@SafeVarargs
чтобы подавить предупреждение. Для интерфейсов используйте@SuppressWarnings("unchecked")
.Если вы получили это сообщение об ошибке:
и вы уверены, что ваше использование безопасно, тогда вы должны использовать
@SuppressWarnings("varargs")
вместо этого. См. @SafeVarargs соответствующую аннотацию для этого метода? и https://stackoverflow.com/a/14252221/14731 для хорошего объяснения этого второго вида ошибки.Ссылки:
источник
Object[]
. До тех пор, пока вы не бросаетеObject[]
, это звучит так, как будто вы должны быть в порядке.static <T> void bar(T...args) { ((Object[])args)[0] = "a"; }
. А потом позвониbar(Arrays.asList(1,2));
.Object[]
почему компилятор выдает предупреждение, если я этого не сделаю? В конце концов, это должно быть довольно легко проверить во время компиляции (в случае, если я не передаю его другой функции с аналогичной сигнатурой, в этом случае другая функция должна вызвать предупреждение). Я не верю, что это действительно суть предупреждения («Ты в безопасности, если не произносишь»), и я до сих пор не понимаю, в каком случае я в порядке.bar(Integer...args)
). Так в чем же смысл этого предупреждения?@SafeVarargs
не препятствует этому, однако требует, чтобы компилятор был более строгим при компиляции кода, который его использует.http://docs.oracle.com/javase/7/docs/api/java/lang/SafeVarargs.html объясняет это более подробно.
Загрязнение кучи происходит, когда вы получаете,
ClassCastException
когда выполняете операцию с универсальным интерфейсом, и оно содержит другой тип, чем объявленный.источник
Когда вы используете varargs, это может привести к созданию
Object[]
аргумента для хранения аргументов.Благодаря экранированию, JIT может оптимизировать создание этого массива. (Один из немногих случаев, когда я обнаружил, что это так). Его нельзя оптимизировать, но я не буду беспокоиться об этом, если вы не обнаружите проблему в профилировщике памяти.
AFAIK
@SafeVarargs
подавляет предупреждение от компилятора и не меняет поведение JIT.источник
@SafeVarargs
.Причина в том, что varargs дают возможность вызываться с непараметризованным массивом объектов. Так что, если ваш тип был List <A> ..., он также может быть вызван с типом List [] не-varargs.
Вот пример:
Как видите, List [] b может содержать любой тип потребителя, и все же этот код компилируется. Если вы используете varargs, то у вас все хорошо, но если вы используете определение метода после стирания типа - void test (List []) - тогда компилятор не будет проверять типы параметров шаблона. @SafeVarargs отключит это предупреждение.
источник