java 泛型与通配符(?)

泛型应用于泛型类或泛型方法的声明。

如类GenericTest

public class GenericTest<T> {

    private T item;
    public void set(T item) {
        this.item = item;
    }
    public T get() {
        return item;
    }
}

有该类生成对象时可以选择相应的类型,GenericTest<Integer> test = new GenericTest<>();    GenericTest<String> test = new GenericTest<>();

java中比较常见的是容器类,如List<Double> list = new ArrayList<>(),Map<Integer,String> map = new HashMap<>();

 通配符(?)应用于泛型的使用

通配符是拿来使用定义好的泛型的,如使用上述泛型类的方法,

    public void test(GenericTest<?> obj) {
        System.out.println(obj);
    }

如List<?> list = new ArrayList<String>();   理论上?使list可以添加任何元素,但List<?>这种写法不能向list中添加任何元素(除了null),list.add("abc");  list.add(56); 都会报错。无法确定添加元素的类型,就无法分配内存大小。

较为常见的是<? extends T> 或者 <? super T> 带有边界的通配符。

List<? extends T> 表明list中的元素都是T及T的子类,List<? super T> 表明list中的元素都是T及T的父类。

Integer是Number的子类,但ArrayList<Integer>不是ArrayList<Number>的子类,装Number的list并不能装Integer。ArrayList<Number> list = new ArrayList<Integer>(); // 错误。

改为ArrayList<? extends Number> list = new ArrayList<Integer>(); 则是正确的。

<? extends T>不能往里存,只能向外取。

List<? extends Number> list = new ArrayList<>();

list.add(3);    // 错误
list.add(2.2); // 错误

Number n = list.get(0);       //正确
float f = (float)list.get(1);  //正确

(猜想)由于子类对象占用内存的大小>=父类对象,故向list中添加元素时不能为对象分配合适的内存大小。list中的元素都是Number及其子类,故取出的元素都可以转为Number类。

<? super T> 可以向里存,也可以向外取。

List<? super Integer> list = new ArrayList<>();

list.set(0, 2);                  // 正确

int a = (int)list.get(0);    // 正确

猜你喜欢

转载自www.cnblogs.com/deltadeblog/p/8977480.html
今日推荐