我正在阅读有关varargs堆污染的内容,我并不真正了解varargs或non-reifiable类型将如何解决那些在没有通用性的情况下尚未存在的问题.的确,我可以很容易地取代
public static void faultyMethod(List<String>... l) {
Object[] objectArray = l; // Valid
objectArray[0] = Arrays.asList(42);
String s = l[0].get(0); // ClassCastException thrown here
}
Run Code Online (Sandbox Code Playgroud)
同
public static void faultyMethod(String... l) {
Object[] objectArray = l; // Valid
objectArray[0] = 42; // ArrayStoreException thrown here
String s = l[0];
}
Run Code Online (Sandbox Code Playgroud)
第二个只是使用数组的协方差,这实际上是问题所在.(即使List<String>
是可以恢复的,我想它仍然是子类,Object
我仍然可以将任何对象分配给数组.)当然我可以看到两者之间有一点差别,但是这个代码是错误的,无论是是否使用泛型.
它们对堆污染的意义是什么(它让我考虑内存使用情况,但他们谈到的唯一问题是潜在的类型不安全),它与使用数组协方差的任何类型违规有何不同?
我们使用了一些varargs函数,当我们转向java 1.7时,我们得到了一个奇怪的未经检查的警告.
功能在接口ICache中添加
public interface ICache<O> {
void add(Object source, O... objects);
}
Run Code Online (Sandbox Code Playgroud)
在界面中报告错误.
ICache.java:18: warning: [unchecked] Possible heap pollution from parameterized vararg type O
void add(Object source, O... objects);
where O is a type-variable:
O extends Object declared in interface ICache
1 warning
Run Code Online (Sandbox Code Playgroud)
O扩展了Object,作为其通用缓存类.
我阅读了xlint警告并且我们在未经检查的情况下编译,但是http://docs.oracle.com/javase/7/docs/technotes/tools/windows/javac.html#xlintwarnings似乎暗示这个错误应该是[varargs]类型不是未经检查的类型.
我错过了什么吗?
我正在尝试决定在每次使用参数化的varargs(例如in)时遇到Java堆污染警告时该怎么做
public static <T> LinkedList<T> list(T... elements) {
...
}
Run Code Online (Sandbox Code Playgroud)
在我看来,如果我有信心不在我的方法中使用一些奇怪的演员,我应该@SafeVarargs
继续使用并继续前进.但这是正确的,还是我需要更加小心?使用参数化varargs时,是否有明显正确的代码实际上不安全?
阅读有关该主题的内容,我注意到提供的示例非常人为.例如,Java文档显示以下错误方法:
public static void faultyMethod(List<String>... l) {
Object[] objectArray = l; // Valid
objectArray[0] = Arrays.asList(42);
String s = l[0].get(0); // ClassCastException thrown here
}
Run Code Online (Sandbox Code Playgroud)
这是教诲但非常不现实; 有经验的程序员不太可能编写代码来做这样的事情.另一个例子是
Pair<String, String>[] method(Pair<String, String>... lists) {
Object[] objs = lists;
objs[0] = new Pair<String, String>("x", "y");
objs[1] = new Pair<Long, Long>(0L, 0L); // corruption !!!
return lists;
}
Run Code Online (Sandbox Code Playgroud)
这显然是以一种不切实际的方式混合类型.
那么,在参数化的变量下,堆污染会发生更微妙的情况吗?@SafeVarargs
如果我没有以丢失输入信息的方式转换变量,或者错误地混合类型,我是否有理由使用?换句话说,我是否有理由将这一警告视为一种不太重要的形式?
我有一个像下面这样的构造函数
public MyConstructor(MyObject<T> ... objects) {
// ...
}
Run Code Online (Sandbox Code Playgroud)
Eclipse通过以下消息警告我:
类型安全:通过varargs参数对象潜在的堆污染
我改变了这样的构造函数:
public MyConstructor(MyObject<T>[] objects) {
// ...
}
Run Code Online (Sandbox Code Playgroud)
现在,警告消失了.但是,我认为潜在的危险并未解决.
这种解决方法有效吗?