有人可以帮我找出如何应用Type erasure / generics来使其工作。
Set<? extends Object> ss = new HashSet<Integer>();
Set<? extends Object> sa = new HashSet<Integer>();
ss.addAll(sa);
现在它抛出了编译错误,因为它会在编译时检查类型。
答案 0 :(得分:1)
我相信你可以认为你的类型擦除源看起来像
Set ss = new HashSet();
set sa = new HashSet();
ss.addAll(sa); // compilation error
如果已编译
$ cat Erased.java
import java.util.*;
public class Erased {
public static void main(final String[] args) {
final Set<Integer> ss = new HashSet<Integer>();
final Set<Integer> sa = new HashSet<Integer>();
ss.addAll(sa);
}
}
$ javap -c Erased
Compiled from "Erased.java"
public class Erased {
public Erased();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String[]);
Code:
0: new #2 // class java/util/HashSet
3: dup
4: invokespecial #3 // Method java/util/HashSet."<init>":()V
7: astore_1
8: new #2 // class java/util/HashSet
11: dup
12: invokespecial #3 // Method java/util/HashSet."<init>":()V
15: astore_2
16: aload_1
17: aload_2
18: invokeinterface #4, 2 // InterfaceMethod java/util/Set.addAll:(Ljava/util/Collection;)Z
23: pop
24: return
}
这是反编译的源代码
import java.util.HashSet;
import java.util.Set;
public class Erased
{
public static void main(String[] paramArrayOfString)
{
HashSet localHashSet1 = new HashSet();
HashSet localHashSet2 = new HashSet();
localHashSet1.addAll(localHashSet2);
}
}
答案 1 :(得分:1)
首先你知道它为什么不起作用吗?
它们是两个独立的通配符。虽然看起来一样,但它们仍然是分开的。因此,第一个? extends Object
(实际上你可以简单地写它?
)与第二个不同。
而且,无论何时使用通配符,都不要指望引用该类型。但是,您在addAll()
中这样做需要进行类型检查。
如果在方法中使用这些逻辑,则可以为方法提供正确的类型参数:
public static <T> void addToFirst(Set<T> first, Set<T> second) {
first.addAll(second);
}
因此可以进行类型检查以确保第一个和第二个具有相同的类型。
使用原始类型可能是另一种选择。
问问自己是否真的需要在类型参数中使用通配符。简单地使用Set<Integer>
应该是最直接的。