Java泛型初探

概述
  1. 泛型就是参数化类型,一提到参数,最熟悉的就是定义方法时有形参,然后调用此方法时传递实参,其实你回味一下这里。形参参数化的是变量的值,而如果你想参数化变量的类型,那就用到泛型了。同样的, 定义的时候叫类型形参,使用时传入类型实参
    1. 所以很多时候你会遇到,定义一个方法的时候,形参的类型和值都是用变量表示的,比如:<T> T[] toArray(T[] a);
  2. 所以 , 泛型就是把类中或者方法中某些数据的类型也作为参数来传递,使得代码更加灵活
  3. 对比:
    1. 我把以前的做:参数化变量、变量形参、变量实参
    2. 现在的叫做:参数化类型、类型形参、类型实参
  4. 其实两个还有很大区别的:
    1. 参数化变量只在定义方法的时候会使用,对类没有参数化变量一说,实例化类传递的参数实际上只是构造方法的参数
    2. 而参数化类型不仅在定义方法的时候使用,还在定义类的时候会使用到,这点上它会带来很大的不同
      1. 参数化类型能通过形式参数限定实际参数范围。类比参数化变量,是这样的样子:比如变量类型是Int,你要求int的范围是0到100,于是有 int<100> a;
      2. 本来类之间的相对关系只有一个维度(虽然类似是一个树图),两个类之间有明确的上下关系或者是没有关系(即使算上多重继承),但如果一个类又有了参数化类型的尾巴的话,那类之间的关系又有了一个新的维度,造成的结果可能是这个维度上,A在上B在下,而在另一个维度,B在上A在下,不过目前JAVA就规定尾巴的维度不使用
        1. 这里可能对于尾巴这个维度有一点异议,因为它比较复杂
          1. 在定的时候,一般如果是<T>,那这个维度可以说没有,但如果对这个T有extends的话,那确实会有一个范围,会有一个上下关系
          2. 在使用的,这种上下关系就很明显了,T本身的取值就是类型,它的上下关系会造成外面 Class<T>的上下关系吗
      3. 对类的使用场景有:定义类的时候,实例化类的时候,声明对象类型的时候(多态)
        1. 前两种情况比较简单,但是第三种情况就需要实际面临上面提到的问题【在使用的,这种上下关系就很明显了,T本身的取值就是类型,它的上下关系会造成外面 Class<T>的上下关系吗 】,你需要找到一个基类
 
泛型分 泛型类/接口 和 泛型方法
  1. 实例化泛型类的时候需要显式传递泛型参数,使用泛型方法则一般通过参数传递
 
而应用情景又分为:
  1. 定义泛型时(定义泛型时只能发生在 类/接口的定义 和方法的定义时)
    1. 定义泛型--类/接口,就是在定义类的时候指定某个类型为参数。形式是这样,<>写在定义的类的名称的后边: class Box<T> { .......}
    2. 定义泛型--方法,就是在定义方法的时候指定某个类型为参数。形式是这样,<>写在方法的public 后 void前:public  <T> T[] toArray(T[] a);
  2. 使用泛型时
    1. 使用泛型可以发生在 任何时候,包括 类/接口的定义 和方法的定义时
    2. 使用方法就是把本来应该写类型名称的位置改成你定义的泛型形参名字 , 形式非常简单
  3. 声明对象类型的时候(多态)
 
下面要做一些拓展(两个层次的上下限):
  1. 类Box<T>中可以向T传入不同的类型参数。T作为形式参数(注意T是传入 类型名,(相当于Object啊),不是对象,这点很特殊,不是多态)
    1. 可以限制T的类型范围,在<T>中标记类型限定:
      1. 不管该限定是类还是接口,统一都使用关键字extends
      2. 跟类的继承使用的关键字是一样的,这里的特点是,这个关键字写在<>里
      3. 这里extends的意思是,T可以是他们的子类(不能是XX的父类。跟没节操的下面不一样)
      4. 可以使用&符号给出多个限定
      5. 如果限定既有接口也有类,那么类必须只有一个,并且放在首位置
      6. 比如 Box<T extends Object&Comparable&Serializable>
  2. 另一个层面(上面说的是Box<T> 中的T,下面要说有<T>这个尾巴的Box<T>本身) ,当【Box<T>这个类的对象】要【作为参数】进行传递的时候,用什么作为它的基类呢?(注意,这里就是传统的传递对象了,用基类和多态完成)
    1. 实验证明,Box<Fruit>和Box<Apple>之间没有等级关系,应该是都为Box类。但是这个Box基类要如何表示呢
    2. JAVA给了一种方法,Box<?>是Box<具体类型名>的基类,于是方法可以是这样:
      public static void getData(Box<?> data)
    3. 而且另一个层面,可以限制用Box<?>作为类型形参传入的Box<具体类型名>对象的范围,在形式参数Box<?>上标记通配符上下限:
      1. 注意点:为什么说另一个层面,因为在对 method(Box<?>  data) 这个整体来看时,它作为一个参数的类型的限定,跟普通的 method(Box data) 对比
        1. 普通的method(Box data) ,表示data的类型,只能是Box类型,或者是Box子类
        2. 而method(Box<?>  data),表示data的类型,只能是Box<各种>的类型,无他
        3. 同时在method(Box<?>  data)中加入了上下限,再缩小了【Box<各种>】的范围,变成【Box<上下限>】
      2. 具体用法:
        1. Box<? extends int>  ;意思是,可以传入以int的所有衍生类作为具体类型名参数的Box类型的对象(然后这个对象本身还可以传入多种不同的类型,也就是它有两重限制的样子)
        2. Box<? super int>;意思是,可以传入以int的所有父类作为具体类型名参数的Box类型的对象
posted @ 2016-03-23 15:21  赛艇队长  阅读(333)  评论(0编辑  收藏  举报