了解具有void返回类型的泛型参数

时间:2015-05-06 09:01:19

标签: java generics

我正在查看JDK类的源代码。

以下方法签名让我困惑:

public static <T extends Comparable<? super T>> void sort(List<T> list);

由于该方法没有返回任何形式的所有形式类型参数?

如果方法的签名只是这样,方法的行为会如何变化:

public static void sort(List<T> list);

5 个答案:

答案 0 :(得分:5)

如果是

public static void sort(List<T> list);

Java不知道应该从参数中推断出T类型。它会寻找一个名为T的具体类或接口,找不到它,并向您吐出编译器错误。

答案 1 :(得分:3)

语法:

public static void sort(List<T> list);

不合法,因为T尚未声明。具有正确语法的最接近的代码是:

public static void sort(List<?> list);

这意味着该方法将接受任何类型的List,但是要排序列表,必须有一些方法来比较它的元素 - 因此原始签名:

public static <T extends Comparable<? super T>> void sort(List<T> list);

这意味着可以通过compareTo()方法将每个元素与其他所有元素进行比较。

语法:

void sort(List<? extends Comparable> list)

几乎没有那么有用 - 它只要求列表包含可比较的对象,但不一定是彼此。例如,list可以包含一个String和一个Integer,它们都是Comparable,但彼此不能 - 你无法对这样的列表进行有意义的排序。这是因为每个元素的未知类型可能不同。但是,通过键入方法,类型仍然可以是任何类型,但它是列表中所有元素的相同类型。

答案 2 :(得分:1)

Sierra&amp; Bates SCJP:

  

泛型方法最奇怪的是你必须在方法的返回类型之前声明类型变量。

正如其他人所说,唯一的方法是

public static void sort(List<T> list);

工作是否实际上有一个名为T的类,在这种情况下,参数就像变量的任何其他类型声明一样。

也可以考虑一下来自Sierra&amp; amp;贝茨。它显示正式类型参数是为了避免命名冲突

class X { public <X> X(X x) {} } 
  

是的,这有效......类名,类型参数占位符和变量标识符之间没有命名冲突。

然后我们还有其他案例:

void sort(List<? extends Comparable> list)

此案例称为capture of a wildcard。编译器从通配符获取类型规范并创建匿名类型。效果与显式类型规范相同,只是该类型不能在方法实现中使用。您可以将其想象为以下伪代码:

<T_?001> void sort_?001(List<T_?001> list)

本案例展示了形式参数的另一个目标 - 它们允许在方法实现中使用命名类型

<T extends Comparable> void sort(List<T> list) {
  Iterator<T> it = list.iterator();
}

答案 3 :(得分:0)

此处类型参数仅用于将输入列表限制为仅实现Comparable接口的元素。感谢通用参数,如果传递List个非可比元素,则会出现编译时错误。

答案 4 :(得分:0)

type参数与方法的行为无关,它与方法的签名有关。该方法仅接受可比较的列表。如果你输入一个不可比较的列表,那么sort就会失败 - 这是有意义的,因为如果无法比较这些元素,你想如何对它们进行排序?