简体   繁体   中英

Generic declaration in method

What does the generic type declaration <T> right before the return type of the get method in the following code example mean?

public interface Listener<T, R> {
    <T> Listener<T, R> get();
}

I understand its meaning in the class declaration of Listener but I did not find a practical example using <T> in that way for a method.

It is a method scoped parameterized type. It is defined only in the scope of the get() method and it hides the T declared in the Listener class.
Hiding type is something to avoid and defining a method scoped parameterized type in a generic class is often questionable.

I want to know what is the role of the parameter in that place.

Here T is a type inferred by the client of the method.
But as this T is distinct of the T declared in the class, it can be a distinct type.
If you want to convert the T of the generic class to another type specified by the client it could make sense. For example suppose the implementation :

public class MyListener implements Listener<String, Integer>{

    @Override
    public <T> Listener<T, Integer> get() {
        return convert to T and return a new instance of Listener...;
    }

}

So you could write :

MyListener myListener = new MyListener();
Listener<Float, Integer> listener = myListener.get();

Note that the returned Listener and MyListener are not compatible types.


I would add that your interface is actually a functional interface as it declares a single abstract instance method.
Using generic method doesn't allow to use functional interface with lambdas body but only with method references.

For example these could not compile :

Listener<String, Integer> invalidListener = () -> new MyListener<String, Integer>();
Listener<String, Integer> invalidListener2 = () -> new MyListener<>();

while the method reference will compile :

Listener<String, Integer> validListener = MyListener::new;

This is a method specific parametrized type, but... There is already defined T and R parameters in the interface so this should be avoided since it hides the defined parameter from the interface.

The correct usage example would be in the case the interface defines only parameter R :

public interface Listener<R> {
    <T> Listener<R> get(T t);
}

However, even this usage is questionable. The example is clear - the interface works with parameter R and only its method uses T additionally. Another method without this <T> singature would not be able to use T .

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