周末研究了下java泛型,关于泛型通配符的协变与逆变问题,题目如下:
- 题目要求:创建一个泛型类Generic1<T>,它只有一个方法,将接受一个T类型的参数。创建第二个泛型类Generic2<T>,它也只有一个方法,将返回类型T的参数。编写一个泛型方法,它具有一个调用第一个泛型类的方法的逆变参数。编写第二个泛型方法,它具有一个调用第二个泛型类的方法的协变参数。
- 实例代码如下:
package generics.exercises;
import java.util.ArrayList;
import java.util.List;
import typeinfo.pets.Dog;
public class ContraVarianceAndCovariant {
static class Generic1Sup<T> {
}
static class Generic1<T> extends Generic1Sup<T> {
void setT(T t) {
}
}
static class Generic1Sub<T> extends Generic1<T> {
}
static class Generic2Sup<T> {
}
static class Generic2<T> extends Generic2Sup<T> {
T getT(T t) {
return t;
}
}
static class Generic2Sub<T> extends Generic2<T> {
}
static <T> void writeWithWildcard(List<? super T> list, T item) {
list.add(item);
}
static <T> T readCovariant(List<? extends T> list) {
return list.get(0);
}
static List<Generic1<Dog>> dogs = new ArrayList<Generic1<Dog>>();
static List<Generic1Sup<Dog>> dogsSup = new ArrayList<Generic1Sup<Dog>>();
static List<Generic1Sub<Dog>> dogsSub = new ArrayList<Generic1Sub<Dog>>();
static List<Generic2<Dog>> dogs2 = new ArrayList<Generic2<Dog>>();
static List<Generic2Sup<Dog>> dogs2Sup = new ArrayList<Generic2Sup<Dog>>();
static List<Generic2Sub<Dog>> dogs2Sub = new ArrayList<Generic2Sub<Dog>>();
static void f1() {
writeWithWildcard(dogs, new Generic1<Dog>());
writeWithWildcard(dogsSup, new Generic1<Dog>());
// ! writeWithWildcard(dogsSub, new Generic1<Dog>());
Generic1<Dog> generic1 = dogs.get(0);
generic1.setT(new Dog("dog1"));
System.out.println(generic1);
}
static void f2() {
Generic2<Dog> generic2 = readCovariant(dogs2);
generic2 = (Generic2<Dog>) readCovariant(dogs2Sup);
generic2 = readCovariant(dogs2Sub);
generic2.getT(new Dog("dog2"));
System.out.println(generic2);
}
static class CovariantReader<T> {
T readCovariant(List<? extends T> list) {
return list.get(0);
}
}
static void f3() {
CovariantReader<Generic2<Dog>> fruitReader = new CovariantReader<Generic2<Dog>>();
Generic2<Dog> generic2 = fruitReader.readCovariant(dogs2);
// ! generic2 = fruitReader.readCovariant(dogs2Sup);
generic2 = fruitReader.readCovariant(dogs2Sub);
generic2.getT(new Dog("dog2"));
}
}
感兴趣的读者可以研究下,为题目提供更好的解决方案。