何时在泛型方法的声明中使用<T>

Mik*_* S. 7 java generics methods

这有什么区别:

T getById(Integer id);
Run Code Online (Sandbox Code Playgroud)

还有这个:

<T> T getById(Integer id);
Run Code Online (Sandbox Code Playgroud)

他们不是都返回一个类型的类T吗?

Sot*_*lis 8

在第一个片段中,T引用了类'类型参数列表中声明的类型变量.

在第二个片段中,您将创建一个新的类型变量T(可能会影响第一个类),在方法参数列表中声明.


Ste*_*ppo 7

是的,但你必须在T某个地方宣布.你做了什么改变.

  • 在第一种情况下,T是在类级别定义的,因此您的方法是泛型类的一部分,并且在声明/实例化时必须专门化该类.T对于类中的所有方法和属性都是一样的.
  • 在第二个中,T是在方法级别定义的,因此它是一个通用方法.T罐头(通常)的价值可以推断出来.

在第一种情况下,范围T是整个类,而在第二种情况下,只是方法.

第二种形式通常与静态方法一起使用.此外,后者的优点是T可以推导出类型变量(在大多数情况下你不必指定它),而你必须为前者指定它.

特别是,你将不得不使用一个通用类,如果它的某些属性取决于T(有型的T,List<T>等等).


JB *_*zet 7

第一个返回封闭泛型类型的类型T. 例如,

T get(int index);
Run Code Online (Sandbox Code Playgroud)

在类中声明的List<T>返回类型为T的元素在给定的索引处List<T>.

第二个声明方法本身是一个泛型方法,其返回类型取决于它被调用的方式.如果你调用它

String s = theObject.<String>getById(id);
Run Code Online (Sandbox Code Playgroud)

它将返回一个String.如果你调用它

Foo f = theObject.<Foo>getById(id);
Run Code Online (Sandbox Code Playgroud)

它将返回一个Foo.大多数情况下,泛型类型是由编译器自动推断的,因此您可以简单地编写

Foo f = theObject.getById(id);
Run Code Online (Sandbox Code Playgroud)

有关具体示例,请参阅

static <T> T max(Collection<? extends T> coll, Comparator<? super T> comp)
Run Code Online (Sandbox Code Playgroud)

它返回T的集合中T类型的最大元素.方法返回的类型取决于传递给方法的集合的类型.