Java Generics WildCard:<?extends Number> vs <T extends Number>

vik*_*.rk 62 java generics

这两个功能有什么区别?

static void gPrint(List<? extends Number> l) {
    for (Number n : l) {
        System.out.println(n);
    }
}

static <T extends Number> void gPrintA(List<T> l) {
    for (Number n : l) {
        System.out.println(n);
    }
}
Run Code Online (Sandbox Code Playgroud)

我看到相同的输出.

Thi*_*ilo 42

在这种情况下没有区别,因为T从未再次使用过.

声明a的原因T是您可以再次引用它,从而将两个参数类型或返回类型绑定在一起.

  • 如果只有一个`?`,则它是等价的.如果有多个`?`,那么你必须使用`T`或`?`,这取决于你是否需要两种类型相同,或者想要允许它们不同.如果你有一个方法`x(<?extends Number> a,<?extends Number> b)`,你可以用Integer和Long调用它.如果你有`T a,T b`,它们都需要是同一类型. (9认同)

Boh*_*ian 42

不同之处在于您T在使用通配符时无法参考.

你现在不是,所以"没有区别",但是你可以用这些T来改变它们:

static <T extends Number> T getElement(List<T> l) {
    for (T t : l) {
        if (some condition)
            return t;
    }
    return null;
}
Run Code Online (Sandbox Code Playgroud)

这将返回传入的任何类型相同的类型.例如,这些将编译:

Integer x = getElement(integerList);
Float y = getElement(floatList);
Run Code Online (Sandbox Code Playgroud)

  • 通配符实际上并不是"需要",但是当它确实是未绑定类型(不需要为其命名)时提供更少的输入.结果代码是等效的.这类似于`int a = 1; 返回a`与`return 1`.或者写`<T extends Object>`而不是`<T>` (2认同)

ns8*_*s89 9

T是一种有界类型,即你使用的任何类型,你必须坚持扩展的特定类型Number,例如,如果你将Double类型传递给列表,你不能传递Short类型T的类型Double,并且列表已经受到限制类型.相反,如果你使用?(wildcard),您可以使用"任何"类型的扩展Number(同时添加ShortDouble到该列表).