简体   繁体   中英

Java methods and generics

Why are generics declared as part of a method? For instance, when creating a method that uses generics, the generics must be included after the method modifiers:

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

The generics portion of a method is not shown as part of a method declaration. According to java documentation, methods contain the following items:

Modifiers—such as public, private, and others you will learn about later.

The return type—the data type of the value returned by the method, or void if the method does not return a value.

The method name—the rules for field names apply to method names as well, but the convention is a little different.

The parameter list in parenthesis—a comma-delimited list of input parameters, preceded by their data types, enclosed by parentheses, (). If there are no parameters, you must use empty parentheses.

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

This is because you have to consider separately generic type parameters declaration and usage .

In a method declaration without the first <T,K> , like this:

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

the compiler wouldn't know that T and K are supposed to be method type parameters (inferred from the method call). It would expect T and K to be already declared (eg imported), because these are usages of generics, not declarations.

That's why you need the declaration <T, K> after the modifiers for the compiler, telling it that T and K are type parameters inferred from the method call.

The problem does not occur when you declare a generic class like this:

public class MyClass<T> {
}

because there is no other meaning T could have here, that can only be a type parameter declaration .


Note: you can also tell the difference between declarations and usages, because you can constrain a type parameter during its declaration, but not during its usage. This is valid:

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

While this is not:

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

Why isn't the compiler smarter?

You could tell me that the compiler could be smart and it could see that the type is not declared, and deduce it is supposed to be generic. But it would really be a mess if it were so.

In most cases your method won't be generic. In most cases, a parameter like List<Something> would be used where Something is actually defined already. Imagine if you simply forget to import the Something class...

The compiler would assume a generic type parameter, erased by object, and you would not understand why you're not able to use your class's methods etc. It would take some time to realize what's wrong, because the compiler would accept such a declaration.

For a more authoritative and complete source of documentation, you should refer to the Java Language Specification. Specifically in this case section 8.4 on method declarations where they explicitly mention type parameters:

A method declares executable code that can be invoked, passing a fixed number of values as arguments.

MethodDeclaration:

{MethodModifier} MethodHeader MethodBody

MethodHeader:

Result MethodDeclarator [Throws]

TypeParameters {Annotation} Result MethodDeclarator [Throws]

MethodDeclarator:

Identifier ( [FormalParameterList] ) [Dims]

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

Generics is just an abbreviation for “generic types”, that can be expressed for return types or for parameter types (like in your case: AbstractDao<T, K> ). And the syntax of the language requires that the type variables specified in the generic types should be declared before the return type of the method, so that they can encompass both return as well as parameter types.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM