java – Why use a generic return?

Question:

I was looking at the method signature of the Optional class and I didn't understand what this <T> in front of the empty() method's return means:

public static <T> Optional<T> empty()

It returns an Optional<T> , right!?
But why use a <T> in front of the method's return?

Answer:

understanding the syntax

Considering the important part:

<T> Optional<T> empty()

T is a variable of type . This works more or less like a variable in a template , where you can replace T with any type, remembering that type in Java is synonymous with class (not to be confused with *primitive types).

The first <T> says: this method is going to use a generic type T somewhere. It's like a hint to the compiler (and the inattentive programmer).

The return type of the Optional<T> method then says that the generic type of Optional must be the same generic type as the method.

Confused, right? When will Java know the T type? This happens at the moment you are going to use the method. As @Maniero said, when you call the method by assigning the result to a certain type, Java can infer the type used in that call.

For example, if you are assigning the method's return to a variable of type Optional<String> , then T = String and you can read the method as:

Optional<String> empty()

In fact, more advanced IDEs like Eclipse and IntelliJ will show the signature with the proper replacement of T during autocompletion whenever it's possible to infer type from the current context.

Keep in mind that generic type inference is a compile-time guarantee that there will be no incompatibility between types during assignments and accesses. Therefore, this does not influence the execution of the program.

Another example

This is not the only way the compiler understands the generic type. A classic example is a method that returns the same type passed by parameter:

static <T> T instanciar(Class<T> classe) throws IllegalAccessException, InstantiationException {
    return classe.newInstance();
}

As in the first example, <T> says that the method is generic, the return will be of type T and the method receives a class of type Class<T> . Example of use:

Cliente c = instanciar(Cliente.class);
Produto p = instanciar(Produto.class);

How does Java infer the T type here? The compiler looks at the class type passed in the parameter and thus guarantees that the returned value is of the same type.

Unlike the case in the question, where the type is inferred by the variable that receives the method's return, here the type is inferred by one of the informed parameters.

For example, Cliente.class is an attribute that returns an object of type Class<Cliente> , so the return from the first call will be of type Cliente , where T = Cliente .

Because <T> is required before method type

There are generic classes/interfaces and generic methods. If the class/interface is generic, its methods can use the generic type.

Example:

interface Generico<T> {
    T empty();
}

Or:

class Generico<T> {
    T empty() { ... }
}

However, if only the method is generic, the declaration must come before the method. This goes for static and instance methods.

Note that you can mix generic classes and methods and use different names for type variables:

class Generico<T> {
    T empty() { ... }
    static <X> Optional<X> empty() { ... }
    <Y> Optional<Y> of(Y instance) { ... }
}

However, consider that there is a convention for typed variable names .

I believe that the decision to require a generic type declaration was made for code readability reasons, in addition to avoiding obscure syntaxes so as not to confuse a generic type T with a class T {} .

Is the generic type strictly necessary?

No. Java generics are just a safety issue for the programmer.

You might as well do this:

public static Optional empty() {
    return Optional.empty();
}

And back to the Java 1.4 era, where there were no generics, but instead casts and ClassCastException errors ClassCastException everywhere.

Scroll to Top