扫盲

  1. 泛型协变
    这样调用是报错的

    改一下

    double类型的列表可以被认为成number类型的子类,协变使得泛型的约束更加宽松,这样把doubleList当做numberList传进去是合法的

  2. 泛型逆变

    联接:
    https://www.bilibili.com/video/BV1nS4y137Mi/?spm_id_from=333.788&vd_source=ec88851bfe4aabc1bf818fbf8600b7de

泛型上下边界

List<? extends Animal>, 通配符的上限,不能往里存,只能往外取,因为编译器只知道容器里的是父类或者父类的子类,但不知道它具体是什么类型,所以存的时候,无法判断是否要存入的数据的类型与容器种的类型一致,所以会拒绝set操作

<? super E>通配符的下限,往外取只能赋值给Object变量,不影响往里存,因为编译器只知道它是子类或者它的父类,这样实际上是放松了类型限制,父类一直到Object类型的对象都可以往里存,但是取的时候,就只能当成Object对象使用了

<? extends T>表示该通配符所代表的类型是T类型的子类
<? super T>表示该通配符所代表的类型是T类型的父类

总结 ? extends 和 the ? super 通配符的特征,我们可以得出以下结论:
◆ 如果你想从一个数据类型里获取数据,使用 ? extends 通配符(能取不能存)
◆ 如果你想把对象写入一个数据结构里,使用 ? super 通配符(能存不能取)
◆ 如果你既想存,又想取,那就别用通配符


  1. 泛型方法
// 泛型类
class Box<T> {
    /**
     * 在泛型类中声明了一个泛型方法,使用泛型E,这种泛型E可以为任意类型,可以类型与T相同,也可以不同。
     * 由于泛型方法在声明的时候会声明泛型<E>,因此即使在泛型类中并未声明泛型,编译器也能够正确识别泛型方法中识别的泛型。
     */
    public <E> void B_1(E t) {
        System.out.println(t.toString());
    }

    /**
     * 在泛型类中声明了一个泛型方法,使用泛型T,注意这个T是一种全新的类型,可以与泛型类中声明的T不是同一种类型。
     *
     */
    public <T> void B_2(T t) {
        System.out.println(t.toString());
    }

    // 不是泛型方法
    public void B_3(T t){
        System.out.println(t.toString());
    }
}
  • 所有泛型方法声明都有一个类型参数声明部分(由尖括号分隔),该类型参数声明部分在方法返回类型之前(在上面例子中的<E>、<T>);

  • 只有声明了<T>、<E>的方法才是泛型方法(B_1、B_2),泛型类中使用泛型的成员方法不是泛型方法(B_3);

  • <T>、<E>表明该方法将使用泛型类型T、E,此时才可以在方法中使用泛型类型T、E;

  1. <T> T 和 <T> List<T>
    下面看一段代码
/**
* 第一个《T》 表示泛型
* 第二个表示返回的实T类型的数据
* 第三个表示限制参数类型为T
*/
public static <T> T map(Object source, Class<T> destinationClass) {
    return null == source ? null : dozer.map(source, destinationClass);
}
/**
* 第一个《T》 表示泛型
* 第二个表示返回的实List<T>类型的数据
* 第三个表示限制参数类型为T的类
*/
public static <T> List<T> copyList(Collection sourceList, Class<T> destinationClass) {
    List<T> destinationList = new ArrayList();
    if (null != sourceList) {
        Iterator var3 = sourceList.iterator();

        while(var3.hasNext()) {
            Object sourceObject = var3.next();
            T destinationObject = dozer.map(sourceObject, destinationClass);
            destinationList.add(destinationObject);
        }
    }

    return destinationList;
}

泛型实现原理

Java泛型:<? extends XXXX> 中的? 和 extends 的理解和使用实例

部分节选自文章



实际上编译器不仅关注一个泛型方法的调用,它还会为某些返回值为限定的泛型类型的方法进行强制类型转换,由于类型擦除,返回值为泛型类型的方法都会擦除成 Object 类型,当这些方法被调用后,编译器会额外插入一行 checkcast 指令用于强制类型转换,这一个过程就叫做『泛型翻译』。

分类: java

0 条评论

发表评论

Avatar placeholder

您的电子邮箱地址不会被公开。 必填项已用*标注

站点统计

  • 文章总数:304 篇
  • 分类总数:19 个
  • 标签总数:189 个
  • 运行天数:852 天
  • 访问总数:460606 人次
ICP备案号: 辽ICP备20003309号