Java方法和泛型

时间:2015-07-31 17:32:18

标签: java generics methods

为什么泛型声明为方法的一部分?例如,在创建使用泛型的方法时,必须在方法修饰符之后包含泛型:

public static <T, K> void delete(AbstractDao<T, K> dao)

方法的泛型部分未显示为方法声明的一部分。根据java文档,方法包含以下项目:

  

修改器 - 例如公共,私人和其他您稍后将了解的内容。

     

返回类型 - 方法返回的值的数据类型,如果方法未返回值,则返回void。

     

方法名称 - 字段名称的规则也适用于方法名称,但约定略有不同。

     

括号中的参数列表 - 以逗号分隔的输入参数列表,以其数据类型开头,括在括号中,()。如果没有参数,则必须使用空括号。

参考:https://docs.oracle.com/javase/tutorial/java/javaOO/methods.html

4 个答案:

答案 0 :(得分:10)

这是因为您必须单独考虑通用类型参数声明用法

在没有第一个<T,K>的方法声明中,如下所示:

public static void delete(AbstractDao<T, K> dao)

编译器不知道TK应该是方法类型参数(从方法调用推断)。我们希望TK已经被声明(例如导入),因为这些是泛型的用法,而不是声明。

这就是为什么在编译器的修饰符之后需要声明<T, K>的原因,告诉它TK是从方法调用中推断出的类型参数。

当您声明这样的泛型类时,不会发生此问题:

public class MyClass<T> {
}

因为T没有其他含义,只能是类型参数声明

注意:您还可以区分声明和用法之间的区别,因为您可以在声明期间约束类型参数,但不能在其使用期间约束。这是有效的:

public static <T extends Pony, K> void delete(AbstractDao<T, K> dao)

虽然不是这样:

public static <T, K> void delete(AbstractDao<T extends Pony, K> dao)

为什么编译器更聪明?

你可以告诉我编译器可能是智能的,它可以看到没有声明类型,并推断它应该是通用的。但如果是这样的话,那真是一团糟。

在大多数情况下,您的方法不会是通用的。在大多数情况下,在List<Something>已经实际定义的地方使用Something之类的参数。想象一下,如果你只是忘记导入Something类......

编译器将假设一个泛型类型参数,由对象擦除,你不明白为什么你不能使用你的类的方法等。这需要一些时间来实现什么&#39 ; s错了,因为编译器会接受这样的声明。

答案 1 :(得分:2)

有关更具权威性和完整性的文档来源,请参阅Java语言规范。特别是在这种情况下section 8.4 on method declarations,他们明确提到了类型参数:

  

方法声明可以调用的可执行代码,将固定数量的值作为参数传递。

     

MethodDeclaration:

     
    

{MethodModifier} MethodHeader MethodBody

  
     

MethodHeader:

     
    

Result MethodDeclarator [Throws]

         

TypeParameters {Annotation} Result MethodDeclarator [Throws]

  
     

MethodDeclarator:

     
    

Identifier ( [FormalParameterList] ) [Dims]

  

答案 2 :(得分:1)

From http://math.hws.edu/javanotes/c10/s5.html“我们需要用类型参数的名称替换方法定义中的特定类型String,例如T.但是,如果这是我们做出的唯一更改,编译器会认为“T”是实际类型的名称,它会将其标记为未声明的标识符。我们需要某种方式告诉编译器“T”是一个类型参数。这就是&lt; T&gt;在泛型类“class Queue&lt;的定义” T> {...“。对于通用方法,&lt; T&gt;就在方法的返回类型名称之前” 所以,&lt; T>在方法名称告诉编译器方法签名中的T不是实际类型,而是泛型。

之前

答案 3 :(得分:0)

泛型只是“泛型类型”的缩写,可以表示返回类型或参数类型(如您的情况:AbstractDao<T, K>)。并且语言的语法要求泛型类型中指定的类型变量应该在方法的返回类型之前声明,以便它们可以包含返回和参数类型。