Java读书笔记-泛型(一)

来源:互联网 发布:java android开发教程 编辑:程序博客网 时间:2024/04/25 10:26

本文为个人摘抄《Java 核心技术 卷I(第十版)》

Java 中的泛型

为什么要使用泛型程序设计?

泛型程序设计(Generic programming)意味着编写的代码可以被很多不同类型的对象重用

在没有泛型的时候,泛型设计是怎么实现的?答案是使用继承

    public class ArrayList //before generic class    {        private Object[] elementData;        ...        public Object get(int i){...}        public void add(Object o){...}    }

对于使用这种方法,会出现两个问题:
1. 如果要获取一个值,必须进行强制类型转换(因为返回值是Object型)
2. 没有错误检查机制,可以添加任何类的对象(所有类都是Object型)
泛型提供了更好的解决方案:类型参数,如ArrayList就用类型参数来指示元素类型:

ArrayList<<String>> files=new ArrayList<String>();

使用类型参数的好处是
1. 使得代码具有更好的可读性
2. 使得编译器知道调用相应方法的时候的返回值类型,不需要用Object进行强制类型转换。
3. 编译器可以进行检查,避免插入错误类型的对象。

定义简单泛型类

一个泛型类就是具有一个或多个类型变量的类

public class Pair<T> //引入 类型变量T ,并用尖括号扩起,可以有多个泛型,用逗号隔开 如 <T,U>{   private T first; //成员变量为类定义中的变量类型   private T second;   public Pair() { first = null; second = null; }   public Pair(T first, T second) { this.first = first;  this.second = second; }   public T getFirst() { return first; } //方法返回类型为类定义中的变量类型   public T getSecond() { return second; }   public void setFirst(T newValue) { first = newValue; }//方法参数类型为类定义中的变量类型   public void setSecond(T newValue) { second = newValue; }}

注意:一般来说,类型变量使用大写形式,而且比较短
在Java 库中,使用变量E表示集合的元素类型,K,V表示关键值对、T、U、S表示任意类型

初始化时,用具体的类型变量替换类型变量的位置即可实例化

Pair<String>

除了泛型类以外,我们还可以在类中定义泛型方法

Class ArrayAlg{    Public staitc <T> T getMiddle(T…a) //类型变量放在修饰符后面 返回类型前    {        Return a[a.length/2];    }}

调用时在尖括号中放入具体类型

String middle=ArrayAlg.getMiddle("John","Q","Public");

几乎大多数泛型调用是没有问题的,但是还是会有情况会出错

Double middle =ArrayAlg.getMiddle(3.14,1729,0)

在这里编译器会自动打包参数为一个Double和2个Interger对象,然后寻找这些类的共同超类,而后找到Number和Comparable接口,但是本身他们也是泛型类型。
如果想要不出错,只能把参数全部改成double \让参数具有共同超类

类型变量 的限定
看到上面的例子,有时我们需要对类型变量进行一点小小的约束。比如下面计算数组最小元素的例子
public static T min(T[] a)
变量类型为泛型,意味着可以是任何一个类的对象,怎么样才能限定进入方法的变量具有compareTo方法呢?
那么,可以按照这样的方法对类型变量设置限定(bound)实现:

class ArrayAlg{  public static <T extend Comparable> T min(T[] a)   {    if(a==null|| a.length==0)     {       return null;     }     T smallest=a[0];     for(int i=0;i<a.length;i++)     {       if(smallest.compareTo(a[i])>0)        {          smallest=a[i];        }     }     return smallest;  }}

这样如果没有实现Comparable的类调用就会产生编译错误
一个类型变量或者通配符可以有多个限定
例如

T extends Comparable &Serializable //限定类型用 "&" 分隔

在继承中,一个类只能继承一个类,但是可以实现多个接口,所以在泛型的限定中,至多有一个类,如果使用一个类作为限定,那么它必须是限定列表中的第一个。