I\'m just learning about generics in Java from a textbook, where it talks about a class GenericStack
implemented with an ArrayList
There are two parts to this:
The generic type parameter given for the class definition is available within the class itself.
You can have generic types specific to individual methods (including constructor).
Look at the following example:
package snippet;
import java.util.ArrayList;
public class Y<E> extends ArrayList<E> {
public <T> Y(T t) {
}
}
Where as the type E
is available to the whole of the class, the type T
is valid only within the constructor.
You are confusing a method's declaration with its call site (that is, where you use it). If you want to use a generic that's declared on the class, only ever need to provide the <E>
or <>
at the call site — not the declaration. And in that regard, a constructor is declared like any other method:
public GenericStack<E> {
public E get() { ... // correct
public <E> put(E element) { ... // bad (see below)
public GenericStack() { ... // correct, like the get()
Redeclaring the generic (as in the put
case above) actually shadows it; the E
in put(E)
is actually a different E
than in GenericStack<E>
, despite having the same name. This is confusing, and you should avoid doing it.
Both the class and the constructor can be generic on their own, i.e. each has its own type parameters. For example
class A<T>
{
<S>A(S s){}
}
To invoke the constructor with all explicit type arguments
new <String>A<Integer>("abc"); // T=Integer, S=String
Think of it like this, A<Integer>
is the concrete class, and <String>A
is the concrete constructor.
Because of type inference, we can omit the type argument for the constructor
new A<Integer>("abc"); // S=String is inferred
The type argument for the class can also be omitted and inferred, by "diamond" (<>
) syntax
A<Integer> a = new A<>("abc"); // T=Integer is inferred, as well as S=String
I wrote a (long) post on this subject - https://stackoverflow.com/a/32292707/2158288