Java基础知识(四)

简单的泛型类

  1. 泛型程序设计意味着编写的代码可以被很多不同类型的对象所重用。

  2. 一个泛型类(generic class) 就是具有一个或者多个类型变量的类,且泛型类中可以有多个类型变量,类定义中的类型变量指定方法的返回类型以及域和局部变量的类型。

    如:public class Pair\{…}

    ​ private T first;

  3. 在Java库中,使用变量E表示结合的元素类型,K和V分别表示表的关键字与值得类型,T(U,S) 表示任意类型。

泛型方法

  1. 定义泛型方法时,类型变量放在修饰符(如public,static等)的后面,返回类型的前面。

    如:

    1
    2
    3
    4
    5
    class ArrayAlg{
    public static <T> T getMiddle(T... a){
    return a[a.length/2];
    }
    }
  2. 泛型方法可以定义在普通类中,也可以定义在泛型类中,当调用一个泛型方法时,在方法名前的尖括号放入具体的类型也可以省略。

    如: String middle= ArrayAlg.\getMiddle();

    该调用中的<String>即可省略。

类型变量的限定

\

  • 表示T应该是绑定类型(BoundingType)的子类型,T和绑定类型可以是类,也可以是接口。
  • 限定类型用”&”分隔,类型变量用”,”分隔
  • 在Java的继承中,可以根据需要拥有多个接口超类型,但限定至多只有一个类;如果用一个类作为限定,他必须是限定列表中的第一个。

泛型代码和虚拟机

  1. 虚拟机没有泛型类型对象,所有对象都属于普通类。
  2. 无论何时定义一个泛型类型,都自动提供了一个相应的原始类型。原始类型的名字就是删除类型参数后的泛型类型名。 擦除类型变量,并替换为限定类型(无限定用Object)。
  3. 类型擦除可能与多态发生冲突,可以利用桥方法来保持多态。
  4. 所有的类型参数都用他们的限定类型替换。

约束与局限性

  1. 类型参数不能使用基本类型,原因是类型擦除后,泛型类含有Object类型的域,而其不能存储基本类型(如double)的值。

  2. 所有的类型查询只产生原始类型

    如:

    1
    2
    3
    4
    Pair<String> stringPair=...;
    Pair<Employee> employeePair=...;
    if(StringPair.getClass()==employeePair.getClass())
    //they are equal,与类型变量无关
  3. 不能创建参数化类型的数组,但是生命类型为Pair\[]的变量仍为合法的,不过不能用new Pair\[10]初始化。

    如果需要手机参数化类型对象,唯一安全有效的方法时使用ArrayList: ArrayList<Pair<String>>

  4. 不能构造一个泛型数组,如果数组仅仅作为一个类的私有实力域,就可以将这个数组声明为Object[],并且在获取元素时进行类型转换。P541

  5. 不能在静态域或者方法中引用类型变量

    如:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    public class Singleton<T>{
    private static T singleInstance; //ERROR
    public static T getSingleInstance() //ERROR
    {
    if(ssingleInstance==null) construct new instance of T
    return singleInstance;
    }
    }

    类型擦除之后,T失效,只剩下Singleton类。

泛型类型的继承规则

  1. 无论S与T有什么联系,通常,Pair\与Pair\没什么联系。
  2. 泛型类可以扩展或实现其他的泛型类。例如:ArrayList\类实现了List\接口。

通配符类型

通配符?与类型变量T的区别及使用

JAVA泛型通配符T,E,K,V区别,T以及Class\,Class<?>的区别

  1. 通配符的超类型限定(例)

    ? super Manager

    这个通配符限制为Manager的所有超类型,带有超类型限定的通配符可以为方法提供参数,但不能使用返回值

  2. 通配符的子类型限定(例)

    ? extends Employee

    这个通配符限制为Employee的所有子类型,可以接受方法的返回值,但不能提供参数。即可以使用get()方法,但是无法使用set()方法。

  3. 带有超类型限定的通配符可以向泛型对象写入,带有子类型限定的通配符可以从泛型对象读取。

  4. 无限定通配符

    Pair<?>

    Pair<?>与Pair的本质不同在于:可以用任意Object对象调用原始的Pair类的setObject方法。