• Java 泛型程序设计


    1.  泛型类

    public class Pair<T> 
    {
       private T first;
       private T second;
       
       public void setSecond(T second){...}
       ....
     }

    2.  泛型方法

    class ArrAlg{
        public static  T getMiddle(T... a){
            return a[a.length/2];
        }
    }

    3.   类型变量的限定

    public static extends BoundingType1 & BoundingType2 ...> T min(T[] a)....

    这表示T应该是BoundingType类型的子类型。T和绑定类型可以是类,也可以是接口 。一个类型变量或通配符可以有多个限定,但限定中之多只有一个类,这是因为单继承,当有多个限定时,基类要写在第一个,接口写在后面。

     

    4.  原始类型,任何一个泛型类型,都自动提供一个原始类型,原始类型的名字就是删去类型参数后的类型名。例如Pair, 原始类型就是Pair。

    5.  泛型转换

    •   虚拟机中没有泛型,只有普通的类和方法
    •        所有的类型参数都用它们的第一个限定类型替换,没有写明限定类型就用Object
    •        合成桥方法保持多态。
    •        为保持类型安全性,必要时插入强制类型转换(例如调用泛型方法返回值)

    5.  桥方法

    假设有下列类继承了Pair,

    class DateInterval extends Pair
    {
        public void setSecond(Date second){
        ....
       
        }
     }

     实际擦除类型之后 

    class DateInterval extends Pair
    {
        public void setSecond(Date second){...}
        
        //因为类型擦除,实际还存在一个继承于Pair类的方法,显然这是两个方法
        public void setSecond(Object second){
             //实际生成桥方法,这里会调用setSecond(Date seconde);即:
             setSecond((Date)second);
         }
     }

    当如下调用时 Pair pair = new DateInterval(...);  pair.setSecond(aDate);。Pair类型只有一个方法setSecond(Object)。实际引用DateInterval类,因而将会调用DateInterval.setSecond(Object)。编译器为了调用最合适的方法,实际上生成了一个桥方法,如下 public void setSecond(Object second){  setSecond((Date) second)  } 。

    6.  约束与局限性

    • 不能用基本类型实例化类型参数
    • 运行时类型查询只适用于原始类型
    • 不能创建参数化类型的数组,即不能 new Pair [10]
    • 不能实例化类型变量,即不能使用 new T(...), new T[] 或T.class这类的表达式。可以通过反射实例化T但不能T.class.newInstance(); 可以如下设计API来实现。

     

    public static  Pair makePair(Class cl){
        try{
            return new Pair<>(cl.newInstance(), cl.newInstance())
            }catch(Exception e){return null;}
    }
    • 泛型类的静态上下文中不能引用类型变量,例如 private static T aData; 或者 public static T fun(){}都是错误的。
    • 不能抛出或捕获泛型类的实例

    7.  通配符

    • 通配符限定: extends 、super

    例:Pair表示泛型Pair类型,它的参数是Person的子类。

    在这种情况下,getter和setter区别,getter可以正常调用,但是setter不行,会产生编译错误,因为编译器不能确定要传入参数的类型,也没法代替。

     

    ?extends Person getFirst()
    void setFirst(? extends Person)

    反之,通配符的超类型限定: ?super Student

    void setFirst(? super Student);
    ? super Student getFirst();

    编译器虽然不知道setFirst的确切类型,但是可以用任意Student对象调用,而不能用Person对象调用。如果调用getFirst,返回的对象不能保证,只能赋给Object。

    • 无限定通配符 Pair
    ? getFirst();
    void setFirst(?);

    getFirst的返回值只能赋给一个Object, setFirst不能调用除非setFirst(null),对于一些简单操作非常有用,例如判定是否为null  getFirst() == null

    • 通配符捕获   可以通过泛型方法捕获通配符 
  • 相关阅读:
    论文解读(Geom-GCN)《Geom-GCN: Geometric Graph Convolutional Networks》
    当三年前端开发掌握了工程化,真就无敌了?
    yum升级mysql
    JAVA每日面试题
    单应性矩阵在标定中的应用
    大学英语六级单词记录
    【C++】Cmake简易教程与模板
    vue——后台权限界面(el-tree)
    表单校验wed第十九章
    【SpringCloud微服务全家桶学习笔记-GateWay网关(微服务入口)】
  • 原文地址:https://www.cnblogs.com/lostO/p/16706006.html