繁体   English   中英

Java泛型 - 除了下界之外的通配符的用途?

[英]Java generics - purpose of wildcard except for lower bounds?

使用通配符进行无界或上限泛型的目的是什么? 进一步来说:

为什么我会说public static void foo(List<?> bar)而不是public static <E> void foo(List<E> bar)

为什么我会说public static void foo(List<? extends Baz> bar)而不是public static <E extends Baz> void foo(List<E> bar)

如果您不打算在后面的代码中引用E ,则无需声明它。

减少程序员的内存压力。

如果在运行时决定列表的类型,则需要使用通配符。

如果使用任何命令行参数运行,以下程序将打印List<String> ; 否则会打印List<Number>

public class Test {

    public static List<String> listOfStrings = Arrays.asList("hello", "world");
    public static List<Number> listOfNumbers = Arrays.asList(1, 2, 3, 4.5);

    public static List<?> getListOfUnknown(boolean arg) {
        if(arg) return listOfStrings;
        else return listOfNumbers;
    }

    public static void main(String[] args) {
        System.out.println(getListOfUnknown(args.length > 0));
    }
}

带通配符的版本是首选。 如果参数的类型为List<?> ,则很明显将接受任何List 如果接受任何List ,则没有理由给type参数一个名称,因此写<E>只会是混乱的。 另一方面,如果类型参数在签名中出现两次,则无法使用通配符。 例如,此签名需要一个类型参数。

public static <E> List<E> combineLists(List<E> list1, List<E> list2)

实际上在那个例子中,如果参数类型为List<? extends E> List<? extends E> (没有通配符的唯一方法就是有三个类型参数,一个混乱)。

在Effective Java中,建议即使方法体中需要type参数,也应该更喜欢带有通配符的签名版本,并编写一个私有帮助方法来实现这一点。 例如:

public static void swapFirstAndLast(List<?> list) {
    helper(list);
}

private static <E> void helper(List<E> list) {
    int size = list.size();
    E e = list.get(0);
    list.set(0, list.get(size - 1)); // These lines would not be possible
    list.set(size - 1, e);           // If the type of list were List<?>
}

泛型方法的官方教程已经解释得很好。

...类型参数T仅使用一次。 返回类型不依赖于类型参数,也不依赖于方法的任何其他参数(在这种情况下,只有一个参数)。 这告诉我们类型参数用于多态; 它唯一的作用是允许在不同的调用站点使用各种实际的参数类型。 如果是这种情况,则应使用通配符。 ...

通用方法允许使用类型参数来表示方法和/或其返回类型的一个或多个参数的类型之间的依赖关系。 如果没有这种依赖关系,则不应使用通用方法。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM