The difference between <T extends A> void foo (T t) and void foo (A a)
Little.
On the other hand, consider this method:
public <T extends A> T transform(T t); And caller code:
class B implements A { ... } B result = transform(new B(...)); This would not be possible (it will not compile above, since the compiler will force you to declare the result type as A ) if you declared the method as
public A transform(A a) When using one object there is no difference. But imagine if you had
class B extends A { ... } and
public void f(List<A> list) { ... }; and
public <T extends A> void f(List<T> list) { ... }; with the first, you can pass a list that exactly matches the type of List<A> . With the second, you can pass a list containing objects that extend A However, with the first you cannot do the same. So, in other words, you could not pass List<B> first method, but you could use the second method.
In your case there is no difference, because the type parameter is used only in one place. Both methods will accept anything that is A or extends A. The general method will make more sense in this case, because the type parameter allows you to associate the return value with the passed parameter:
public <T extends A> T f(Class<T>) {...} Regardless of whether it depends on what is inside this function.
The point of generics is to provide type safety. Suppose A has two subclasses, call them B and C. In the first example, using f (List <A>), the list can include B, C, or a mixture of both. But in the second example, f <T extends A> (List <T>), when we call the function, we must specify the type. If we say f <B>, then we know that this is list B, not allowed C. We will not be allowed to go to list C or general A, we cannot add C to the list, and everything we choose will be guaranteed B.
For better or worse, it depends on what you are trying to do. If the idea is that you need a list that is either all B or all C, then the general way helps this. If you need a list, which can be one of two, then you do not want to use a common one, use a simple f (List <A>).