简体   繁体   English

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

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

What is the purpose of using a wildcard for unbounded or upper-bounded generics? 使用通配符进行无界或上限泛型的目的是什么? More specifically: 进一步来说:

Why would I say public static void foo(List<?> bar) instead of public static <E> void foo(List<E> bar) ? 为什么我会说public static void foo(List<?> bar)而不是public static <E> void foo(List<E> bar)

Why would I say public static void foo(List<? extends Baz> bar) instead of public static <E extends Baz> void foo(List<E> bar) ? 为什么我会说public static void foo(List<? extends Baz> bar)而不是public static <E extends Baz> void foo(List<E> bar)

If you are not ever going to refer to E in the code that follows, there is no need to declare it. 如果您不打算在后面的代码中引用E ,则无需声明它。

Reduces programmer memory strain. 减少程序员的内存压力。

If the type of the list is decided at runtime, then you will need to use wildcards. 如果在运行时决定列表的类型,则需要使用通配符。

The following program will print a List<String> if run with any command-line arguments; 如果使用任何命令行参数运行,以下程序将打印List<String> ; otherwise it will print a List<Number> : 否则会打印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));
    }
}

The versions with a wildcard are preferred. 带通配符的版本是首选。 If a parameter has type List<?> it is clear that any List will be accepted. 如果参数的类型为List<?> ,则很明显将接受任何List If any List is accepted, there's no reason to give the type parameter a name, so writing <E> would just be clutter. 如果接受任何List ,则没有理由给type参数一个名称,因此写<E>只会是混乱的。 On the other hand, if the type parameter appears twice in the signature, then you cannot use wildcards. 另一方面,如果类型参数在签名中出现两次,则无法使用通配符。 For example, this signature needs a type parameter. 例如,此签名需要一个类型参数。

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

Actually in that example it would probably be better if the arguments had type List<? extends E> 实际上在那个例子中,如果参数类型为List<? extends E> List<? extends E> (the only way to do that without wildcards would be to have three type parameters, a total mess). List<? extends E> (没有通配符的唯一方法就是有三个类型参数,一个混乱)。

In Effective Java, it is recommended that even if the type parameter is needed in the body of the method, you should prefer the version of the signature with a wildcard, and write a private helper method to make this possible. 在Effective Java中,建议即使方法体中需要type参数,也应该更喜欢带有通配符的签名版本,并编写一个私有帮助方法来实现这一点。 For example: 例如:

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<?>
}

The official tutorial for generic method already explained well enough. 泛型方法的官方教程已经解释得很好。

... the type parameter T is used only once. ...类型参数T仅使用一次。 The return type doesn't depend on the type parameter, nor does any other argument to the method (in this case, there simply is only one argument). 返回类型不依赖于类型参数,也不依赖于方法的任何其他参数(在这种情况下,只有一个参数)。 This tells us that the type argument is being used for polymorphism; 这告诉我们类型参数用于多态; its only effect is to allow a variety of actual argument types to be used at different invocation sites. 它唯一的作用是允许在不同的调用站点使用各种实际的参数类型。 If that is the case, one should use wildcards. 如果是这种情况,则应使用通配符。 ... ...

Generic methods allow type parameters to be used to express dependencies among the types of one or more arguments to a method and/or its return type. 通用方法允许使用类型参数来表示方法和/或其返回类型的一个或多个参数的类型之间的依赖关系。 If there isn't such a dependency, a generic method should not be used. 如果没有这种依赖关系,则不应使用通用方法。

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

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