程序员

Android中使用泛型

2018-03-22  本文已影响1227人  MinuitZ

泛型是什么

所谓“泛型”,就是“宽泛的数据类型”,任意的数据类型。
我们为什么要使用泛型呢?数据类型为什么要使用"宽泛"的?


设想一下 , 如果我们没有泛型 , 那么我们在使用List的时候, 经常使用到的操作就是存和取 , 但是我们因为不能指定泛型 , 所以只能存入Object类型.

随便说一下

其实 , 在Java中使用的泛型也不是真正意义上的泛型 , 因为我们在编译之后 , 再反编译回java代码的话 , 可以看到编译器自动的把我们的泛型操作还原回了强制类型转换 , 所以我们吧java中的泛型叫做伪泛型 , 把它当做语法糖就好,

泛型使用

首先准备好我们的测试对象Box:

public class Box<T> {

    private T data;

    public T getData() {
        return data;
    }

    public void setData(T data) {
        this.data = data;
    }
}
  1. 直接使用泛型
    这种方式就像普通的List一样 , 规定了数据结构之后 , 直接使用 .
      Box<Number> b=new Box<>();
      b.setData(new Double(1.1));

      Number data = b.getData();

我们也可以在源码中找到类似的使用:

public boolean add(E e) {
        ensureCapacityInternal(size + 1);  // Increments modCount!!
        elementData[size++] = e;
        return true;
    }

其实这种方式和直接使用Object挺像的 , 只是略微灵活了一些 . 但是这就满足了么? 我们可以使用另外一种更舒服更优雅的方法

 public ArrayList(Collection<? extends E> c) {
   ...  ...
}
  1. 设置类型上限<? extends Number>
    用这种方法 , 就可以限定使用泛型的上限了 , 什么叫上限呢 , 就是继承关系的小于 , 不是小于等于 拿ArrayList来举例子
public class ArrayList<E> extends AbstractList<E>

首先,在ArrayList的类定义中就生命了使用泛型E , 那么我们在实例化的时候 , 就规定了E的实际类型 .

public boolean addAll(int index, Collection<? extends E> c) {
            if (index < 0 || index > this.size)
                throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
            int cSize = c.size();
            if (cSize==0)
                return false;

            if (ArrayList.this.modCount != this.modCount)
                throw new ConcurrentModificationException();
            parent.addAll(parentOffset + index, c);
            this.modCount = parent.modCount;
            this.size += cSize;
            return true;
        }

addAll方法中 , 有这样一个限定<? extends E> , 也就是说 , addAll方法允许接收一个集合 , 集合的泛型类型必须是E的子类 . 但必须注意的是 , 这里设置了类型的上限 , 如果超出上限的话 ,会抛出异常的 .

  1. 设置类型下限<? super Number>
    这个和第二点正好相反 , 限定了泛型的类型下限(好像没见过这么玩的)
父类的引用可以指向子类的实例 , 子类的引用无法指向父类的实例
Box<? super Number> box=new Box<>();
box.setData(new Object()); 
/**
*这里会报错 , 因为Object为Number的父类 , 虽然限定了? super Number ,但作为参数 ,
*子类无法指向父类的应用, 即Object不能当成Number使用
**/
box.setData(new Integer(1));
/**
*这里与上面恰好相反 , Integer可以当成Number使用 , 编译通过
*/

乍一看好像有点乱是吧 , 其实在泛型的默认规范中 , 如果破坏了这个规范 , 那么使用泛型就没有太大的意义了

上一篇 下一篇

猜你喜欢

热点阅读