Java基础 (8) 泛型

2019-02-18  本文已影响0人  perry_Fan

问题1:extends和super的区别

泛型

一般的类和方法,只能使用具体类型:要么是基本类型,要么是自定义类型。如果要编写可以应用于多种类型的代码,这种刻板的限制对代码的束缚就会很大。

泛型的诞生?为了更安全友好的使用容器类 : 用来指定容器要持有什么类型的对象,而且由编译器来保证类型的正确性。

1、概述
ArrayList<Fruit> list = new ArrayList<Fruit>();

fruits.add(new Fruit());     // OK
fruits.add(new Apple());     // OK
fruits.add(new Orange());     // OK

fruits.add(new Object());     // Error

上述代码表明了该容器只能保存 Fruit类型 的对象,由于 Apple 也是一种 Fruit,所以其也可以保存 Apple类型 对象,但对于不属于 Fruit类型 的对象,编译器杜绝将其放入列表中。

简单地说:
泛型 = 编译时的类型检查 + 编译时的类型擦除(编译器插入 checkcast 等) + 运行时的自动类型转换。
所以,我们在理解和应用泛型时,一定要从 编译期 和 运行时 两个视角去分析。

2、定义与语法
public class Holder<T>{}
public interface Generator<T>{}
public <T> void f(T x){}
3、extends 与 super 的区别?

协变与逆变
逆变与协变用来描述类型转换(type transformation)后的继承关系,其定义:如果 A,B 表示类型,f(⋅)表示类型转换,≤ 表示继承关系(比如,A ≤ B 表示A是B的子类);

(1)泛型
  令f(A) = ArrayList<A>,那么f(⋅) 是逆变、协变还是不变的呢?如果是逆变,则ArrayList<Integer>是ArrayList<Number>的父类型;如果是协变,则ArrayList<Integer>是ArrayList<Number>的子类型;如果是不变,二者没有相互继承关系。由于实际上ArrayList<Number>和ArrayList<Integer>无关,所以泛型是不变的。

(2)数组
令f(A) = A[],容易证明数组是协变的:
Number[] numbers = new Integer[3];

 ArrayList<? extends Apple> l3 = new ArrayList<>();
 ArrayList<? extends Fruit> l4 = new ArrayList<>();
 l4 = l3;

对于ArrayList<? extends Apple>类型,我们知道其表示某种具体类型(只是没有确定下来),但是无论其具体指的是ArrayList<Apple>类型还是ArrayList<Jonathan>类型都是可以赋给ArrayList<? extends Fruit>类型的引用的,反之则不可以。因此,我们可以认为ArrayList<? extends Fruit>类型是ArrayList<? extends Apple> 类型的父类型,故<? extends>实现了泛型的协变。

  ArrayList<? super Apple> l1 = new ArrayList<>();
  ArrayList<? super Fruit> l2 = new ArrayList<>();
  l1 = l2;

对于 ArrayList<? super Fruit>类型,我们知道其表示某种具体类型(只是没有确定下来),但是无论其具体指的是ArrayList<Fruit>类型还是ArrayList<Object>类型都是可以赋给ArrayList<? super Apple>类型的引用的,反之则不可以。因此,我们可以认为ArrayList<? super Apple>类型是ArrayList<? super Fruit>类型的父类型,故 <? super>实现了泛型的逆变。

引用链接:https://blog.csdn.net/justloveyou_/article/details/52420071

上一篇 下一篇

猜你喜欢

热点阅读