<T extends 是什么意思?

57

我见过一种类似下面所示的方法:

protected <T extends ABC> T save( T Acd, boolean en) {

它是做什么的?在Java中,这种类型的方法声明称为什么?


5
浏览一些教程。你可以从这里开始:- http://docs.oracle.com/javase/tutorial/extra/generics/index.html - Rohit Jain
5
我认为询问一个构造的名称并不是什么坏事!+1 - Rudolf Mühlbauer
7个回答

49

这是一个泛型方法,Java中将其称为“Generics”。该声明表示T可以是任何ABC子类类型。


1
我可以使用任何字母吗?还是只有T是声明泛型方法的唯一类型? - Nigel Thomas
5
您可以使用任何字母。我认为"T"是"类型(Type)"的缩写。在映射结构中,<K,V>表示“键(Key)”和“值(Value)”类型,因此您可以自由选择任何字母。但我建议选择有意义的字母。另外,我不确定是否仅限于字母,您也可以选择一个单词。此外,还有通配符类型,请查阅文档了解更多信息。 - basar
3
你可以使用任何合法的标识符作为泛型类型参数,但惯例规定应该使用大写字母。请参考这个答案:https://dev59.com/THE85IYBdhLWcg3wMAfc。使用单词通常是不好的做法,因为当你看到像 List<Blah> 这样的代码时,你无法确定 Blah 是一个类还是一个类型参数。 - Mark Peters

21

有时候您需要限制传递给类型参数的类型种类。例如,一个操作数字的方法可能只想接受Number类或其子类的实例。这就是bounded type parameters(有界类型参数)的作用。

要声明有界类型参数,请列出类型参数的名称,后跟extends关键字,后跟其上限。 示例:

下面的示例说明了如何在一般情况下使用extends来表示“extends”(如类)或“implements”(如接口)。此示例为通用方法,返回三个Comparable对象中最大的一个:

public class MaximumTest
{
   // determines the largest of three Comparable objects
   public static <T extends Comparable<T>> T maximum(T x, T y, T z)
   {                      
      T max = x; // assume x is initially the largest       
      if ( y.compareTo( max ) > 0 ){
         max = y; // y is the largest so far
      }
      if ( z.compareTo( max ) > 0 ){
         max = z; // z is the largest now                 
      }
      return max; // returns the largest object   
   }
   public static void main( String args[] )
   {
      System.out.printf( "Max of %d, %d and %d is %d\n\n", 
                   3, 4, 5, maximum( 3, 4, 5 ) );

       System.out.printf( "Maxm of %.1f,%.1f and %.1f is %.1f\n\n",
                   6.6, 8.8, 7.7, maximum( 6.6, 8.8, 7.7 ) );

       System.out.printf( "Max of %s, %s and %s is %s\n","pear",
         "apple", "orange", maximum( "pear", "apple", "orange" ) );
   }
}

5
protected <T extends ABC> T save( T Acd, boolean en) {
    // ...
}

在这个函数中,T出现了三次。
  • 有界类型参数: <T extends ABC>
  • 返回类型: T
  • 参数: T Acd
基于这些,我可以回答你的问题如下:

它是做什么的?

save()是一个通用方法,接受两个参数,其中一个参数的类型为T,并返回一个类型为T的值。 T是一种通用类型,限制为ABCT的范围仅限于save()

这种类型的Java方法声明称为什么?

在我看来,答案应该是有界类型参数,而不是泛型。关于Java中的泛型,您可以在这里找到更多信息。

我还想自己添加一个问题:为什么我们需要这样的东西?

有时候,您可能希望限制可用作参数化类型中类型参数的类型。例如,操作数字的方法可能只希望接受Number或其子类的实例。这就是有界类型参数的用途 [1]


4

这是一个通用的保存方法,接受参数T和布尔类型,其中T必须由ABC类进行上限绑定。 ABC类或任何子类都将被接受。


1
我想你的意思是“期望”。 - killjoy
这似乎是最简洁的答案,但为了更完整地解释,save方法还返回类型T,这就是在方法名前加T的原因。这很明显,但不是一眼就能看出来的,也不是在阅读前几个答案后就能理解的。看起来像是方法声明中散布着T,导致代码变得陌生。 - killjoy
"ABC"类也可以使用。这正是我在寻找的。谢谢。 - coretechie

3

这意味着您必须发送一个ABC对象或ABC的子类,不允许使用其他类。此外,您的Acd变量可以使用save方法所在的类可见的ABC类中的方法。

当您的T类扩展接口时,这非常有用。例如,您正在创建一个处理对象数组排序的类,此类必须实现Comparable接口,否则将不允许对数组进行排序:

class Class1 implements Comparable<Class1> {
    //attributes, getters and setters...
    int x;

    //implementing the interface...
    public int compareTo(Class1 c1) {
        //nice implementation of compareTo
        return (this.x > c1.x)? 1 : (this.x < c1.x) ? 0 : -1;
    }
}

class Class2 {
    int x;
}

public class Sorter<T extends Comparable<T>> {

    public static void insertionSort(T[] array) {
        //good implementation of insertion sort goes here...
        //just to prove that you can use the methods of the Comparable interface...
        array[0].compareTo(array[1]);
    }

    public static void main(String[] args) {
        Class1[] arrC1 = new Class1[5];
        Class2[] arrC2 = new Class2[5];
        //fill the arrays...
        insertionSort(arrC1); //good!
        insertionSort(arrC2); //compiler error!
    }
}

3
这在Java中被称为泛型。 官方解释如下:
简而言之,泛型使得类型(类和接口)在定义类、接口和方法时成为参数。就像在方法声明中使用的更熟悉的形式参数一样,类型参数提供了一种方式,让您可以使用不同的输入重复使用相同的代码。不同之处在于,形式参数的输入是值,而类型参数的输入是类型。
非正式地说:
像Java这样的强类型语言会导致更多的错误在编译时而不是运行时出现。这是一件好事。但是它会导致代码重复。为了缓解这种情况,Java添加了泛型。

3

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接