Java通用通配符:<?扩展Number> vs <T扩展Number>


75

这两个功能有什么区别?

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);
    }
}

我看到相同的输出。


5
也许那是因为没有区别吗?
奥利弗·查尔斯沃思


3
为什么我们不能定义类Name <?扩展Number>但类Name <T扩展Number>可以吗?
Prateek Joshi 2015年

@PrateekJoshi是的,我也在想同样的事情。你得到答案了吗?
Terrarium

Answers:


47

在这种情况下没有区别,因为T不再使用。

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


同意!那么有没有唯一的情况呢?会为我完成工作,但不会为“ T”做。还是通配符可以使用'T'来完成?
vikky.rk 2012年

12
如果只有一个?,则等效。如果有多个?,则必须使用T?,这取决于您是否需要使两种类型相同或希望允许它们不同。如果您有一个方法x(<? extends Number> a, <? extends Number> b),则可以用一个整数和一个长整数来调用它。如果您有T a, T b,则它们都必须是同一类型。
Thilo 2012年

1
但是我仍然可以做<T扩展数,U扩展数> x(T a,U b)。那么哪个是首选方式?是否最好不使用通配符(如果可能)?
vikky.rk 2012年

1
这只是样式问题。我更希望使用通配符,以明确表明该类型未绑定到其他类型。
Thilo 2012年

45

区别在于T使用通配符时无法引用。

您现在不是,所以“没有区别”,但是这是您可以T用来改变的方法:

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

这将返回传入的内容相同的类型。例如,它们都将编译:

Integer x = getElement(integerList);
Float y = getElement(floatList);

那么什么时候才真正需要通配符?
vikky.rk,2012年

3
通配符并不是真正的“需要”,但是当确实是一个未绑定的类型(不需要给它起一个名字)时,它提供较少的输入。结果代码是等效的。这类似于与之间的int a = 1; return a区别return 1。还是用文字<T extends Object>代替<T>
Thilo 2012年

@Bohemian等一下,该代码正确吗?是不是在运行时发生类型擦除,导致该代码在运行时失败?
Java博士

1
@ Dr.Java是和否。是的,存在运行时类型擦除,但是在运行时没有错误,因为在编译时可以推断类型并且可以确保类型安全。参见类型推断
波西米亚风格

11

T是有界类型,即无论使用哪种类型,都必须坚持要扩展的特定类型Number,例如,如果将Double类型传递给列表,则不能Short按原样传递T类型Double,并且列表已经受该类型限制类型。相反,如果使用?wildcard),则可以使用扩展的“任何”类型Number(将Short和同时添加Double到该列表)。


-3

使用T时,您可以在List上执行所有类型的操作。但是使用时无法执行添加。

T-与具有完全访问权限的对象引用相同
吗?-提供部分访问权限

static void gPrint(List<? extends Number> l) {
 l.add(1); //Will give error
for (Number n : l) {
    System.out.println(n);
}

static <T extends Number> void gPrintA(List<T> l) {
l.add((T)1); //We can add
for (Number n : l) {
    System.out.println(n);
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.