• 泛型


    泛型:被不同类型的对象所重用

    用继承(objec)实现的两个问题:

    1 获取一个值时必须强制进行类型转换

    2 可以向数组列表中添加任何类的对象

    类型参数:(可读性、安全性)

    定义简单泛型类:

    public class Pari<T>{}

    public class Pair<T,U>{}

    public class HashMap<K,V>{}

    使用泛型类:

    ArrayList<String> files = new ArryList<String>()(两边必须相同)

    ArrayList<String> files = new ArryList()

    ArrayList files = new ArryList<String>()

    使用一个泛型类时,只要在后面加上<具体的类型>

    定义泛型方法(可以在普通类及泛型类中定义):

    class ArrayAlg{

     public static <T> T getMiddle(T...a){  //注意类型变量的位置

         return a[a.length/2]

      }

    }

    泛型方法的调用:

    String middle=ArrayAlg.<String>getMiddle("bb","cc","dd")

    String middle=ArrayAlg.getMiddle("bb","cc","dd")

    类型变量的限定:<T extends BoundingType>这里的T和BoundingType既可以是类也可以是接口,使用extends更加表现出子类的概念

     <T extends BoundingTypeA & BoundingTypeB>可以多个超接口,最多一个类(必须第一个)

    静态方法不能使用类定义的泛形,而应单独定义泛形。 泛形的典型应用:BaseDao和反射泛型

    泛型与虚拟机:

    虚拟机没有泛型类型对象

    泛型代码与虚拟机:

    自动提供原始类型,擦除类型变量,替换为限定类型(无则用object)

    当调用泛型方法时,编译器对返回的object进行强制类型转换

    泛型类擦除造成原本在泛型类子类中覆盖的方法变成了重载。(参数类型变成了object)导致子类出现了同一方法名两种参数的方法,调用时本来只希望调用子类的方法(多态),结果有可能调用了泛型超类中的参数为objec的方法。编译器自动在子类中加入桥方法:

    public void setSecond(object a){setSecond((Date) a)}

    同样在有返回类型的方法中,也会产生两个相同参数类型的方法。虚拟机根据参数类型和返回类型确定一个方法。

    一个方法覆盖另一个方法时可以指定一个更加严格的返回类型。

    1 虚拟机中没有泛型,只有普通类和方法;2 所有类型参数都用他们的限定类型替换 3 桥方法保持多态 4为保持安全性,必要时插入强制类型转换  

    允许泛型代码和遗留代码之间能够互操作。

    泛型的约束与局限(大多由擦除引起):

    1.不能用基本类型实例化类型参数,objec不能储存double的值。

    2.运行时的类型查询只适用于原始类型。使用instanceof,getcalss或泛型类型的强制转化时,都是类型擦除后的效果。

    3.不能创建参数化类型的数组:Pair<String>[] table=new Pair<String>[10]//error,擦除机制将会导致table数组中可以插入任意的Pair<otherclass>

    4.Varargs警告,向参数可变的方法传递一个泛型类型的实例。由于个数可变参数实际上是一个数组,所以会违反第三条,但是只会得到一条警告。

    5.不能实例化类型变量:(如果想通过T来构造对象)

    new T(),T.class//both error

    public Pair(){first=new T();second=new T();}//error

    saddly,由于不能调用T.class:

     first=T.class.newInstance()也是错误的

    如果非要通过反射调用Class.newInstance来构造泛型对象:在Pair中新建一个泛型方法,由于Class本身是泛型,String.class是Class<String>的一个实例



    public
    static <T> Pair<T> makePair(Class<T> cl){ try{return new Pair<>(cl.newInstance(), cl.newInstance()) ;} catch(Exception ex){return null;} }
    调用:
    Pair<String> p = Pair.makePair(string.class);

     不能构造一个类型变量的数组:

    public static <T> T[] minmax(T[] a){T[] mm = new T[2];....}//error

    6. 泛型类的静态上下文中类型变量无效

    7. 不能抛出或捕获泛型类的实例:

    泛型类cannot extend throwable;不能catch类型变量(声明中可以throws类型变量)

    。。。。

    泛型类型的继承规则:

    Pair<employee>和Pair<manager>之间没有关系

    Pair<employee> b=Pair<manager> a //error

    假设可以转换,则会出现可以在b中存储低级别雇员(由于没有保护)

    注意数组和泛型的区别,如果一个manager[]数组赋值给employee[]变量a,则这个变量会带有特别的保护,即低级别雇员无法存储到a[0]。

    Pair<Employee>时原始类型Pair的一个子类型

    泛型类可以扩展或实现其他的泛型类。如ArrayList<T>实现了List<T>接口。

    通配符类型:

    public static void printBuddies(Pair<employee> p){....}

    由于Pair<employee>Pair<manager>之间没有关系,所以上述方法中不能传入Pair<manager>

    引入通配符:public static void printBuddies(Pair<extends employee> p){....}

    Pair<manager>Pair<extends employee>的子类型

  • 相关阅读:
    fis3解决web网站缓存问题
    C# 计算每周和每月固定日期
    移动端web页面上滑加载更多功能
    常见三种字符编码的区别:ASCII、Unicode、UTF-8
    ef AddDays报错
    .NET语言的编译过程:中间语言(IL)和即时编译器(JIT)
    ajax 传递数组类型参数后台接收不到的问题
    sql server 作业没跑、开启sql 代理服务、新建作业
    在javascript中NodeList和Array的区别及转换方法
    我经历的几种开发模式和心理
  • 原文地址:https://www.cnblogs.com/ChuPengcheng/p/5895343.html
Copyright © 2020-2023  润新知