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);
}
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);
}
You should use a generic type when you expect that most of the methods, in the implementations, will perform operations on the type supplied when instantiating the class.
For example,
ArrayList<E>
is a generic type since most of its operations (add, get, remove etc.) rely on the type specified upon creation of one.A generic method should be used when only a few methods in the class rely upon the different types.
You can read more about generics in the Java Docs.
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 forT
while the only thing the implementation can rely on is that the actual type forT
will be assignable toObject
(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 theinterface
:allows implementations like
fixing the type of
T
on the implementation side. Orbeing still generic but restricting the type.
The signature of an
interface
is also important when theinterface
itself is a part of another method signature, e.g.here, the
Flight
implementation, which you pass tofoo
, must be capable of consuming aString
value, soFlight<String>
orFlight<CharSequence>
orFlight<Object>
are sufficient, but notFlight<Integer>
. Declaring such a contract requires type parameters on theinterface
, not at theinterface
’s methods.Take for example the class
java.util.ArrayList<E>
. When creating variables of that type, you have to specify a concrete type forT
:These concrete types are used, when calling methods from the
List
interface, that work with the typeT
. Calling theadd
method, you can only addString
objects to the list. Retrieving elements from the list usingget
, you will get elements of the concrete typeString
.For generic methods, the type
T
is specified only for this method. And it would make more sense if the methods returns a value of that generic type. You often find code like this:or
And you should start your interface name with a capital letter:
Flight<T>