美文网首页Java
泛型基础二

泛型基础二

作者: 静享时光 | 来源:发表于2020-04-24 00:14 被阅读0次

    如果不明白为什么要使用泛型,使用泛型的好处,以及泛型类,泛型接口,泛型方法等知识,请移步泛型基础一

    通配符

    上界通配符

    上界通配符就是限制类型参数是某个类本身或者是其子类。
    例如

      public void dealData2(List<? extends Number> data) {
            /**
             * 
             */
        }
    
    下界通配符

    下界通配符:传入的泛型类型必须是“?”后面指定类型的父类,包括超类Object,以及它自身。

    public void dealData(List<? super Number> data) {
            /**
             *
             */
        }
    
    无界通配符

    无界通配符,就是参数可以是任意类型。
    有两种情况,无界通配符是一种有用的方法:
    1、如果你正在编写可以使用 Object 类中提供的功能来实现的方法。
    2、当代码使用泛型类中不依赖于类型形参的方法时。例如,List.size 或 List.clear。实际上,Class<?> 经常被使用,因为 Class<T> 中的大多数方法都不依赖于 T。

    下面是不使用通配符和使用无界通配符的区别。

    /**
     * 不使用通配符
     *
     * @param dataList
     */
    public void printData(List<Object> dataList) {
        for (Object element : dataList) {
    
        }
    }
    

    我们可以在测试方法中报错了。


    不适用通配符.png

    是因为List<Integer>不是List<Object>的子类,而printData方法中需要的是List<Object>类型,所以会报错。
    我们看下使用通配符的情况:


    使用通配符.png
    可以看到使用通配符之后是没有报错的。

    通配符使用原则

       public void test() {
            List<String> src = new ArrayList<>();
            List<String> dest = new ArrayList<>();
            //public static <T> void copy (List < ? super T > dest, List < ? extends T > src)
            Collections.copy(dest, src);
        }
    

    我们可以把变量分为In变量和Out变量。
    In变量是提供数据,例如上例中的src。src参数提供要复制的数据,所以是In参数。
    Out变量保存数据以供其他地方使用,例如上例中的dest。dest参数接收数据,所以是Out参数。
    通配符的使用指南:
    1、In变量是使用上界通配符定义,使用extends关键字。
    2、Out变量是使用下界通配符定义,使用super关键字。
    3、如果可以使用Object类中定义的方法访问In变量,请使用无界通配符。
    4、在代码需要访问In和Out变量的情况下,不要使用通配符。

    对泛型的限制

    无法使用基本数据类型实例化泛型类型
    原则一.png

    Type argument cannot be of primitive type
    类型参数不能是基元类型

    无法创建类型形参的实例

    泛型不能创建实例,是因为不知道泛型具体的类型


    原则二.png

    Type parameter 'T' cannot be instantiated directly
    类型参数'T'不能直接实例化

    无法声明类型为类型形参的静态字段

    翻译一下就是用类型形参声明的成员变量不能用static修饰。


    原则三.png

    类的静态字段是类的所有非静态对象共享的类级变量。因此,不允许使用类型形参的静态字段。考虑以下类:

    public class MobileDevice<T> {
        private static T os;
    
        // ...
    }
    

    如果允许类型形参的静态字段,则以下代码将混淆:

    MobileDevice<Smartphone> phone = new MobileDevice<>();
    MobileDevice<Pager> pager = new MobileDevice<>();
    MobileDevice<TabletPC> pc = new MobileDevice<>();
    因为静态字段 os 由 phone,pager 和 pc 共享,所以 os 的实际类型是什么?它不能同时为 Smartphone,Pager 和 TabletPC。因此,你无法创建类型形参的静态字段。

    不能使用参数化类型进行类型转换或者使用instanceof
    原则四.png

    Illegal generic type for instanceof
    instanceof的泛型类型不合法


    原则四-1.png

    Inconvertible types; cannot cast 'java.util.List<java.lang.Integer>' to 'java.util.List<java.lang.Number>'
    不可转换的类型;不能将'java.util.List<java.lang.Integer>'转换为'java.util.List<java.lang.Number>

    无法创建参数化类型的数组

    泛型不能是数组,是因为数组具有协变的性质。也就是说
    如果A extends B
    则 A[]也是B[]的子类。
    如果数组是泛型的话,在泛型擦除之后就不满足A[]是B[]的子类了。

    无法创建,捕获或者抛出参数化类型的对象
    原则6.png
    无法重载每个重载的形式参数类型擦除到相同原始类型的方法
    原则7.png

    相关文章

      网友评论

        本文标题:泛型基础二

        本文链接:https://www.haomeiwen.com/subject/systwhtx.html