In the class below, in method m1, is there really any use of mentioning K extends Runnable
before the method return type? I cannot return anything other than Collection<K>
anyways. And if I want to return any subclass of Runnable I would have specified the method like,
static <T> Collection<? extends Runnable> m1(ArrayList<T> l)
Does the K extends Runnable
before the method return type have any significance at all? I get no compilation error for this code either
public class MainClass {
public static void main(String[] args) {
ArrayList<Thread> l = new ArrayList<>();
l.add(new Thread());
l.add(new Thread());
m1(l);
}
static <T, K extends Runnable> Collection<K> m1(ArrayList<T> l) {
ArrayList<K> r = new ArrayList<>();
return r;
}
}
By having the parameter K
, you can let the caller decide what kind of collection it wants back:
public class Test {
static <T, K extends Runnable> Collection<K> m1(ArrayList<T> l) {
ArrayList<K> r = new ArrayList<>();
return r;
}
static void callingIt(){
ArrayList<?> list = new ArrayList<>();
Collection<Thread> threads = m1(list);
Collection<Runnable> runnables = m1(list);
Collection<MyTask> special = m1(list);
}
class MyTask extends Thread{}
}
If you only had Collection<? extends Runnable>
then the caller cannot get back a Collection<Thread>
.
But unless the K
is connected to something else, I cannot see how this would work except for empty result lists (because as soon as you want to add something to r
, you will have to make sure it is an instance of K
).
You can see this pattern being used in Collections.emptyList
:
public static final List EMPTY_LIST = new EmptyList<>();
public static final <T> List<T> emptyList() {
return (List<T>) EMPTY_LIST;
}
The method returns the same thing as the field, but because it is a method, the caller can use it to produce generically typed lists of any type (whereas the field cannot be flexible like this).
There is an unchecked cast in there (with a warning), but since the list is empty, we (unlike the compiler) know it is safe.