真的需要通配符泛型吗?

2022-09-04 08:01:52

例如:

    public String add(Set<?> t){
    ...;
    }



    public <T> String add(Set<T> t){
    ...;
    }

第一个使用通配符泛型;第二个是泛型方法的正常形式。有什么区别?

在什么情况下我们需要通配符泛型,而不是泛型的正常形式?


答案 1

下面是需要通配符的情况。此方法采用 ,这是列表的列表。该方法可以将不同组件类型的列表添加到其中:List<List<?>>

public void foo(List<List<?>> t) {
    t.add(new ArrayList<String>());
    t.add(new ArrayList<Integer>());
}

不能使用不带通配符的泛型类型参数执行此操作。例如,以下操作不起作用:

public <T> void foo(List<List<T>> t) {
    t.add(new ArrayList<String>()); // does not compile
    t.add(new ArrayList<Integer>()); // does not compile
}

答案 2

由于添加了对泛型的支持,因此使用参数化类型而不提供类型参数通常会导致编译器警告。另一方面,在某些情况下,您根本不关心类型参数是什么(即您在任何地方都不使用该类型),或者更糟糕的是,您可能根本不知道是什么,而使用可以让您表达出来而不会引起编译器警告。T<?>

“不在乎”情况的可能用例(为了简洁起见,非常简单,但你明白了):

public void clearList(List<?> list) {
    list.clear();
}

“不知道”情况的一个例子:来自类的实际方法签名:Class

static Class<?> forName(String className);

此处,该方法返回某种类型的对象。 是泛型的,但当然你不知道类型,因为它取决于在运行时解析的参数。所以你不能放在这里,因为在编译时是未知的(即使对于特定的调用站点),并且只使用没有type参数将是一个不好的做法,并导致编译器警告。ClassClassclassNameTTClass


推荐