Android基础系列(1)Java泛型

简述

Java泛型是J2 SE1.5中引入的一个新特性,其本质是参数化类型,也就是说所操作的数据类型被指定为一个参数(type parameter)这种参数类型可以用在类、接口和方法的创建中,分别称为泛型类、泛型接口、泛型方法。
下面我们通过这几个问题来理解Java泛型。

  1. 泛型的作用是什么?
  2. 为什么会有泛型?
  3. 什么是泛型擦除?
  4. 什么是通配符?
  5. 什么是上边界?什么是下边界?

1 泛型的作用

第一个问题,泛型的作用是什么?
简单概括就是,使得类型可以像方法的参数那样传递。

2 为什么会有泛型?

那么为什么会有泛型出现了,这也就要看到泛型出现到底解决了啥问题。
举个例子,现在有一个水缸,然后我们往里面放条红鲤鱼。

// 红鲤鱼对象
public class GreenCarp {
    public void move() {
        System.out.println("绿鲤鱼在吐泡泡!");
    }
}

// 水缸对象
public class Tank {
    private RedCarp redCarp;

    public RedCarp getRedCarp() {
        return redCarp;
    }

    public void setRedCarp(RedCarp redCarp) {
        this.redCarp = redCarp;
    }
}

// 放鱼
public class Test {
    public static void main(String[] args) {
        Tank tank = new Tank();
        tank.setRedCarp(new RedCarp());
        tank.getRedCarp().move();
    }
}

然后我们又想把水缸里换成绿鲤鱼,这个时候,有人可能会直接定义一个Object在水缸对象里。

public class Tank {
    private Object obj;

    public Object getObj() {
        return obj;
    }

    public void setObj(Object obj) {
        this.obj = obj;
    }
}

public class Test {
    public static void main(String[] args) {
        Tank tank = new Tank();
        tank.setObj(new RedCarp());
        ((RedCarp) tank.getObj()).move();
        tank.setObj(new GreenCarp());
        ((GreenCarp) tank.getObj()).move();
    }
}

截屏2021-03-20 下午11.37.45.png
看起来没啥问题,但Object用多了,对于程序员来说也会成为非常麻烦的事情。比如,他有可能没转换为正确的类型,但编译器并不会爆红!运行后却出现错误!

public class Test {
    public static void main(String[] args) {
        Tank tank = new Tank();
        tank.setObj(new RedCarp());
        ((RedCarp) tank.getObj()).move();
        tank.setObj(new GreenCarp());
        ((RedCarp) tank.getObj()).move(); // 写成了RedCarp
    }
}

截屏2021-03-20 下午11.36.33.png
所以,如果我们使用泛型,一切就变得不一样。

public class Tank {
    private T t;

    public T getObj() {
        return t;
    }

    public void setObj(T t) {
        this.t = t;
    }

}

Android基础系列(1)Java泛型_第1张图片

3 泛型擦除

讲泛型擦除前,我们可以看个例子,

public class Test {
    public static void main(String[] args) {
        List l1 = new ArrayList();
        List l2 = new ArrayList();
        System.out.println(l1.getClass() == l2.getClass());
    }
}

各位觉得上面的代码会输出什么?true or false?
Android基础系列(1)Java泛型_第2张图片
答案是true,为什么呢?为什么l1与l2的两个运行时类是相等的。
这就是泛型擦除导致的。
虽然两个对象在编码时候看上去差别很大,但是在运行时已经被反射擦除泛型了。
示例:

List l1 = new ArrayList();
l1.add("8848");
Class c = l1.getClass();
Method m = c.getMethod("add", Object.class);
m.invoke(l1, 8848);
System.out.println(l1);

小结:
泛型擦除是为了兼容jdk老版本的编码。而泛型只存在于编译时期,泛型使编译器可以在编译期间对类型进行检查以提高类型安全,减少运行时由于对象类型不匹配引发的异常。

4 通配符

通配符 ?

Java的继承关系,在泛型中如果不做任何声明修饰,是不被认可的。所以需要泛型处理。

5 上边界与下边界

上边界

? extends T 代表可以传入T或T的子类类型。

下边界

? super T 代表传入必须是T或T的父类类型。

什么时候用上边界?

上边界不能放,因为上边界作用下,不知道要放什么样的类型 所以会报错,但是可以取。
Android基础系列(1)Java泛型_第3张图片

什么时候用下边界?

下边界不能取,因为在下边界的作用下,不知道要取出来什么样的数据,但是可以放。
Android基础系列(1)Java泛型_第4张图片

你可能感兴趣的:(javaandroid)