Java 泛型通配符:<? extends Number> 与 <T extends Number>

问题描述 投票:0回答:5

这2个功能有什么区别?

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

我看到相同的输出。

java generics
5个回答
57
投票

在这种情况下没有区别,因为

T
再也不会被使用。

声明

T
的原因是为了让你可以再次引用它,从而将两个参数类型,或者一个返回类型绑定在一起。


50
投票

区别在于使用通配符时不能引用

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

16
投票

T

 是有界类型,即无论您使用什么类型,都必须坚持扩展 
Number
 的特定类型,例如如果将 
Double
 类型传递给列表,则不能将 
Short
 类型传递给它,因为 
T
 属于 
Double
 类型,并且列表已受该类型限制。相反,如果您使用 
?
 (
wildcard
),则可以使用扩展 
Number
 的“任何”类型(将 
Short
Double
 添加到该列表中)。


0
投票
Java 泛型教程的

上限通配符部分很好地描述了为什么我们使用上限通配符。

正如你所知; Integer、Long、Double 以及其他一些类都是从 Number 类扩展而来的。换句话说,它们都是 Number 的子类型。因此,你可以说“Integer is a Number”、“Double is a Number”等等。 然而,List

与 List、List 等之间不存在相同的关系。换句话说,List 不是 List、List 等的基类型。

因此,假设您想要编写必须能够与所有这些类型的 List 一起使用的方法。换句话说,您的方法应该有一个列表参数,可以是 List

、List、List 等。在这种情况下,您必须 使用上限通配符

总而言之,List

是List、List、List等的基础类型

考虑以下示例:

import java.util.*; public class WildCardDemo { public static double sum1 (List<Number> list) { double result = 0.0; for (Number n : list) { result += n.doubleValue(); } return result; } public static <T extends Number> double sum2 (List<T> list) { double result = 0.0; for (Number n : list) { result += n.doubleValue(); } return result; } public static double sum3 (List<? extends Number> list) { double result = 0.0; for (Number n : list) { result += n.doubleValue(); } return result; } public static void main(String[] args) { List<Double> numList = Arrays.asList(1.0, 2.0, 3.0); //System.out.println(sum1(numList)); // Compiler Error !!! incompatible types: List<Double> cannot be converted to List<Number> System.out.println(sum2(numList)); // This works System.out.println(sum3(numList)); // This works } }
    

-2
投票
当您使用 T 时,您可以在列表上执行所有类型的操作。但使用时无法进行添加。

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); }
    
© www.soinside.com 2019 - 2024. All rights reserved.