Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

like image 660
mattfred Avatar asked Jul 31 '15 17:07

mattfred


People also ask

Why generics are used in Java?

In a nutshell, generics enable types (classes and interfaces) to be parameters when defining classes, interfaces and methods. Much like the more familiar formal parameters used in method declarations, type parameters provide a way for you to re-use the same code with different inputs.

What are generic classes in Java?

A Generic class simply means that the items or functions in that class can be generalized with the parameter(example T) to specify that we can add any type as a parameter in place of T like Integer, Character, String, Double or any other user-defined type.

How does a generic method differ from a generic type?

From the point of view of reflection, the difference between a generic type and an ordinary type is that a generic type has associated with it a set of type parameters (if it is a generic type definition) or type arguments (if it is a constructed type). A generic method differs from an ordinary method in the same way.


3 Answers

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 (e.g. 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.

like image 56
Joffrey Avatar answered Oct 22 '22 03:10

Joffrey


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]

like image 33
M A Avatar answered Oct 22 '22 05:10

M A


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.

like image 39
Renzo Avatar answered Oct 22 '22 05:10

Renzo