Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java Generic Interface vs Generic Methods, and when to use one

Tags:

I was wondering, aside from syntactic difference, when would one use a generic interface over a method that accepts a generic parameter?

public interface Flight<T>{
   void fly(T obj);
}

over

public interface Flight{
    void <T> fly(T obj);
}
like image 277
yev Avatar asked Jun 01 '15 13:06

yev


People also ask

What is a generic method and when should it be used?

Generic methods allow type parameters to be used to express dependencies among the types of one or more arguments to a method and/or its return type. If there isn't such a dependency, a generic method should not be used. It is possible to use both generic methods and wildcards in tandem.

What is the difference between generic class and generic method in Java?

Java Generic methods and generic classes enable programmers to specify, with a single method declaration, a set of related methods, or with a single class declaration, a set of related types, respectively. Generics also provide compile-time type safety that allows programmers to catch invalid types at compile time.

Why do we need generic methods?

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.

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.


1 Answers

If you declare a generic method, you always let the caller decide, which type arguments to use for the type parameters. The implementation of the method must be able to deal with all possible types arguments (and it doesn’t even have a way to ask for the actual type arguments).

That said, a method like <T> void fly(T obj); states that the caller may use any type for T while the only thing the implementation can rely on is that the actual type for T will be assignable to Object (like if <T extends Object> had been declared).

So in this specific example, it’s not different to the declaration void fly(Object obj);, which also allows arbitrary objects.

In contrast, a type parameter on an interface is part of the contract and may be specified or restricted by an implementation of the interface:

public interface Flight<T>{
   void fly(T obj);
}

allows implementations like

public class X implements Flight<String> {
   public void fly(String obj) {
   }
}

fixing the type of T on the implementation side. Or

public class NumberFlight<N extends Number> implements Flight<N> {
   public void fly(N obj) {
   }
}

being still generic but restricting the type.


The signature of an interface is also important when the interface itself is a part of another method signature, e.g.

public void foo(Flight<? super String> f) {
    f.fly("some string value");
}

here, the Flight implementation, which you pass to foo, must be capable of consuming a String value, so Flight<String> or Flight<CharSequence> or Flight<Object> are sufficient, but not Flight<Integer>. Declaring such a contract requires type parameters on the interface, not at the interface’s methods.

like image 187
Holger Avatar answered Oct 07 '22 01:10

Holger