Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why are the angle brackets before the return type omitted sometimes from the definition of a generic method

I was reading Effective Java chapter 5 about generics, in particular the items on preferring generic methods. I noticed that sometimes the type parameter(between angle brackets) in the method declaration before the return type is sometimes omitted. There are many cases like that, but for example on page 135 of the second edition:

public void popAll(Collection<E> dst) {
while (!isEmpty())
dst.add(pop());
} 

On the other hand, I have seen similar generic methods with the declaration

public <E> void ...

Is the first one a typo? If not when can I omit the brackets from the declaration?

Thanks

like image 567
user2262955 Avatar asked Aug 30 '14 18:08

user2262955


2 Answers

E is a type variable -- it stands in for some other type, like String or Integer. So just as you can't understand dst.add(pop()) without knowing where and how dst was defined, you can't understand a method declaration like popAll(Collection<E> dst) without knowing where and how the type variable E is defined. In the case of popAll, the type variable E is defined at the class level: Stack<E>: it's the type of the elements in the stack. You'll often even see it javadoc'd:

/**A Stack of elements
  *
  *@param E The type of elements in the stack */
public class Stack<E>{
    public void popAll(Collection<E> dst){ ... }
}

On the other hand, when you see a method declaration like public <E> void ..., the type variable E is being declared (not referenced from some enclosing scope like the enclosing class). In fact most times when you see a method with its own type variable, it's a static method, so there is no enclosing instance of the class to establish the value of E.

In both cases, what is the E type variable doing? It's telling us how two different types have to relate to each other. In popAll, it's telling us that the element type of the collection you want to put the popped elements into has to match the element type of the stack you're popping them from.

Similarly, take the example from page 136:

public class ListUtils{
    public static <E> E reduce(List<E> list, Function<E> f, E initVal);
}

Here, the E type variable tells us that the element type of list has to match the argument type of f and the type of initVal. The surrounding class does not define E for us, it's only meaningful in the scope of the reduce method declaration.

like image 88
Matt McHenry Avatar answered Sep 28 '22 00:09

Matt McHenry


The difference is that in the first case the whole class is declared generic whereas in the second case only the method is generic.

like image 24
Code-Apprentice Avatar answered Sep 28 '22 02:09

Code-Apprentice