泛型

概念

  • <T>等大写字母标识泛型类型,用于表示未知类型。
  • <T extends ClassA & InterfaceB …>等标识有界泛型类型,用于表示有边界的未知类型。
  • <?>标识通配符,用于表示实例化时的未知类型。
  • <? extends 父类型>标识上边界通配符,用于表示实例化时可以确定父类型的未知类型。
  • <? super 子类型>标识下边界通配符,用于表示实例化时可以确定子类型的未知类型。

T与<?>的区别

  • <T>:泛型标识符,用于泛型定义(类、接口、方法等)时,可以想象成形参。
  class Test<T> {
    private T filed;
  }
  • <?>:通配符,用于泛型实例化时,可以想象成实参
    //我们不能确定具体类型时,可以使用通配符
    Demo1<? extends Number> numberList = null;

    //我们能够确定具体类型时,再实例化成具体类型
    numberList = new Demo1<Integer>();
    numberList = new Demo1<Double>();

转型

  • 向上转型:子类转换成父类,会隐藏子类的一部分信息
  • 向下转型:父类转换成子类,必须使用类型强转,可能会转换失败

边界

上边界类型通配符(<? extends 父类型>):因为可以确定父类型,所以可以以父类型去获取数据(向上转型)。但是不能写入数据。
下边界类型通配符(<? super 子类型>):因为可以确定最小类型,所以可以以最小类型去写入数据(向上转型)。而不能获取数据

上边界

        ArrayList<String> example = new ArrayList<>();
        example.add("a");
        example.add("b");
        example.add("c");

        // 上边界类型通配符(<? extends 父类型>)
        // 无边界类型通配符(<?>) 等同于 上边界通配符<? extends Object>
        List<? extends String> list = null;
        list = example;

        // 因为可以确定父类型,所以可以以父类型去获取数据(向上转型)
        String s = list.get(0);
        // 不可以修改,
        // list.add("aa");

下边界

        // 下边界通配符<? super 子类型> 等同于 下边界通配符<? super 子类型> + 上边界通配符<? extends Object>。
        List<? super String> list2 = null;
        list2 = example;
        // 因为可以确定最小类型,所以可以以最小类型去写入数据(向上转型)
        list2.add("aa");
        // 只能用object类型获取数据
        Object s1 = list2.get(0);

posted @ 2021-03-19 10:42  rm-rf*  阅读(44)  评论(0编辑  收藏  举报