通过变质参数可能产生的堆污染

2022-08-31 04:22:00

我知道Java 7在泛型类型中使用varargs时会发生这种情况;

但我的问题是..

当Eclipse说“它的使用可能会污染堆”时,它到底是什么意思?

新注释如何防止这种情况发生?@SafeVarargs


答案 1

堆污染是一个技术术语。它引用的引用具有不是它们所指向的对象的超类型的类型。

List<A> listOfAs = new ArrayList<>();
List<B> listOfBs = (List<B>)(Object)listOfAs; // points to a list of As

这可能导致“无法解释”的s。ClassCastException

// if the heap never gets polluted, this should never throw a CCE
B b = listOfBs.get(0); 

@SafeVarargs根本无法阻止这种情况。但是,有些方法可以证明不会污染堆,编译器无法证明它。以前,此类 API 的调用方会收到令人讨厌的警告,这些警告完全没有意义,但必须在每个调用站点上被抑制。现在,API 作者可以在声明站点上禁止显示它一次。

但是,如果该方法实际上不安全,则不会再警告用户。


答案 2

当您申报时

public static <T> void foo(List<T>... bar)编译器将其转换为

public static <T> void foo(List<T>[] bar)然后到

public static void foo(List[] bar)

然后会出现一种危险,即您将错误地将不正确的值分配到列表中,并且编译器不会触发任何错误。例如,如果 是,则以下代码将编译而不会出错,但在运行时将失败:TString

// First, strip away the array type (arrays allow this kind of upcasting)
Object[] objectArray = bar;

// Next, insert an element with an incorrect type into the array
objectArray[0] = Arrays.asList(new Integer(42));

// Finally, try accessing the original array. A runtime error will occur
// (ClassCastException due to a casting from Integer to String)
T firstElement = bar[0].get(0);

如果您查看了该方法以确保它不包含此类漏洞,则可以对其进行注释以禁止显示警告。对于接口,请使用 。@SafeVarargs@SuppressWarnings("unchecked")

如果您收到此错误消息:

Varargs方法可能从不可再生的varargs参数造成堆污染

并且您确定您的使用是安全的,那么您应该改用。请参阅@SafeVarargs此方法的合适注释吗?https://stackoverflow.com/a/14252221/14731,了解第二种错误的精彩解释。@SuppressWarnings("varargs")

引用: