堆污染又是啥
最近在看《effective java》的时候,看到一个新鲜词,“堆污染”。乍一看好像是个很高端大气上档次,想起来应该跟jvm关系比较大的概念。
后来学习发现是编写代码不规范可能导致的一个异常现象。下面我们一起来学习下,首先这个东西会牵扯到三个东西,第一个是可变参数,第二个是
泛型,第三个是@SafeVarargs注解。前两个咱们知道是java5中加入的新特性。第三个是在java7中加入的新注解。
问题展示:
我们先来看一段代码,然后看下编译器给了什么提示
public static
return null;
}
1 |
|
static void m(List
Object[] array = stringLists;
List
array[0] = tmpList; // Semantically invalid, but compiles without warnings
String s = stringLists[0].get(0); // Oh no, ClassCastException at runtime!
}
// 写了一个main方法去调用
public static void main(String[] args) {
List
list.add(“1”);
list.add(“2”);
m(list);
}
1 | 运行程序的话,会报出 |
Exception in thread “main” java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String
1 | 因为在 |
String s = stringLists[0].get(0);
1 | 这里stringList[0]已经被array[0] = tmpList修改为了Integer类型的元素,取出来的元素也是Integer类型的,然后因为stringList泛型是String的。 |
public static void main(String[] args) {
String[] attr = pickTwo(“A”, “B”, “C”);
}
static
switch (ThreadLocalRandom.current().nextInt(3)) {
case 0:
return toArray(a, b);
case 1:
return toArray(b, c);
case 2:
return toArray(a, c);
}
throw new AssertionError();
}
static
return args;
}
1 | 想象中的执行过程: |
@SafeVarargs
static
List
for (List<? extends T> list : lists) {
result.addAll(list);
}
return result;
}
首先这是一个泛型可变参数列表的方法,然后和上面toArray的区别是,参数列表变成了泛型的List,返回结果也是变成了List。
然后方法中使用for循环将,所有参数列表的可变参数数组组合成了一个。这样使用就是安全,每一个可变参数的类型的上界都是T,返回的参数最终也都是T。