后面的文章:

  • 详解Java的对象创立
  • 一文打尽Java继承的相干问题
  • 一文打尽Java抽象类和接口的相干问题

本文介绍了Java的泛型的根本应用。

1. 为什么应用泛型

看上面一个例子:

为了阐明问题,本类写的尽量简陋,请把眼光次要放在类型上。

/** * @author Xing Xiaoguan (xingrenguanxue) */public class MyArrayList {    private int[] elementData;    private int size = 0;    public MyArrayList(int capacity) {        elementData = new int[capacity];    }        //向数组中增加元素    public void add(int i) {         if (size == elementData.length) {            throw new IndexOutOfBoundsException("数组已满");        }        elementData[size++] = i;    }        //从数组中依据下标获取元素    public int get(int index) {         if (index < 0 || index > size - 1) {            throw new IndexOutOfBoundsException("超出范围");        }        return elementData[index];    }    @Override    public String toString() {        return "MyArrayList{" +                "elementData=" + Arrays.toString(elementData) +                '}';    }}

该类很简略:有两个成员变量,elementData是一个数组,size是数组中元素的数量。addget办法能增加和获取元素。

上面测试一下:

public class Test {    public static void main(String[] args) {        MyArrayList myArrayList = new MyArrayList(4);        myArrayList.add(111); //向数组中增加3个int元素        myArrayList.add(222);        myArrayList.add(333);        int i = myArrayList.get(0); //获取        System.out.println(i);        //以上失常运行        myArrayList.add("行小观"); //增加一个String元素,类型不匹配,报错    }}

向数组中增加3个int类型的元素并能获取,这没问题。

然而如果咱们的场景不再须要int类型的元素,而是须要String类型的,那怎么办?

很显然,持续应用该类会报错,报错的起因很简略:咱们向数组中增加的元素是String类型的,而数组和办法参数类型是int类型。

此时,就得须要再写一份代码,该份代码较之前的并无大批改,只是把int改为String。如果场景持续变怎么办?那就再写一份新代码!

这样太麻烦了!有没有解决办法?有!

咱们晓得,Object类是所有类的父类,Object类型的变量可能援用任何类型的对象。所以能够将类型改为Object

/** * @author Xing Xiaoguan (xingrenguanxue) */public class MyArrayList {    private Object[] elementData;     private int size = 0;    public MyArrayList(int capacity) {        elementData = new Object[capacity];    }    public void add(Object o) { //向数组中增加元素        if (size == elementData.length) {            throw new IndexOutOfBoundsException("数组已满");        }        elementData[size++] = o;    }    public Object get(int index) { //从数组中获取元素        if (index < 0 || index > size - 1) {            throw new IndexOutOfBoundsException("超出范围");        }        return elementData[index];    }    @Override    public String toString() {        return "MyArrayList{" +                "elementData=" + Arrays.toString(elementData) +                '}';    }}

再测试一下:

public class Test {    public static void main(String[] args) {        //myArrayList 给int元素应用        MyArrayList myArrayList = new MyArrayList(4);        myArrayList.add(111); //向数组中增加3个int元素        myArrayList.add(222);        myArrayList.add(333);        int i = (int) myArrayList.get(0); //获取        System.out.println(i);        //myArrayList 给String元素应用        MyArrayList myArrayList1 = new MyArrayList(4);        myArrayList1.add("aaa");        myArrayList1.add("bbb");        myArrayList1.add("ccc");        String str = (String) myArrayList1.get(1);        System.out.println(str);    }}

发现能够向数组中增加和获取intString类型的元素,这证实该类的数组和办法同时对各种类型的数据都有用,不用再增加额定代码。

然而这样又呈现了两个问题:

第一:从数组中获取元素时,须要强制转换类型才行。

int i = (int) myArrayList.get(0); 

第二:同一个数组能够增加各种类型的元素。

myArrayList.add(111); //int类型myArrayList.add("222"); //String类型myArrayList.add(true); //布尔类型

这就导致了当咱们从数组中获取某个元素时,很难晓得它的确切类型,往往会强转类型失败。

int i = (int)myArrayList.get(1); //原本是String类型的值,但我提前不晓得,拿int变量接管,报错

那这个问题有没有解决办法呢?

有!用泛型!

2. 泛型类

应用泛型革新MyArrayList

/** * @author Xing Xiaoguan (xingrenguanxue) */public class MyArrayList <T> {    private T[] elementData;    private int size = 0;    public MyArrayList(int capacity) {        elementData = (T[]) new Object[capacity];    }    public void add(T o) { //向数组中增加元素        if (size == elementData.length) {            throw new IndexOutOfBoundsException("数组已满");        }        elementData[size++] = o;    }    public T get(int index) { //从数组中获取元素        if (index < 0 || index > size - 1) {            throw new IndexOutOfBoundsException("超出范围");        }        return elementData[index];    }    @Override    public String toString() {        return "MyArrayList{" +                "elementData=" + Arrays.toString(elementData) +                '}';    }}

测试:

public class Test {    public static void main(String[] args) {        //myArrayList 给int元素应用        MyArrayList<Integer> myArrayList = new MyArrayList<>(4);        myArrayList.add(111); //向数组中增加3个int元素//        myArrayList.add("222"); //增加非Integer元素报错        int i = myArrayList.get(1); //无需强制转型        System.out.println(i);      }}

通过革新,咱们把MyArrayList类改为了一个泛型类,它是一个具备多个类型变量的类。

泛型类的申明形式:引入一个类型变量,如T,而后应用<>将其括起来,放在类名后。

public class MyArrayList <T> {    //......}
如何了解类型变量?它就相似于数学中函数中的变量x,用来代替具体的值:

f(x) = 3x + 1

类型变量的名称能够轻易取,个别应用大写字母示意,比方E、K、V、T等。

泛型类中的成员变量、办法参数和返回值的类型都应用类型变量代替:

private T[] elementData;public void add(T o) {    //.......}public T get(int index) {    //......}

当然,一个泛型类能够有多个类型变量:

public class MyClass <K, V> {    //......}

当咱们须要实例化泛型类时,就应用具体的类型来替换类型变量(T):

MyArrayList<Integer> myArrayList = new MyArrayList<>(4);
该过程就相当于向数学函数中代入数值:

f(3) = 3*3+1 = 10

3. 泛型办法

当咱们申明了一个泛型类后,能够很天然地在类外部应用泛型办法。

其实,当类是一般类时,咱们依然可能应用泛型办法。上面是一个例子:

/** * @author Xing Xiaoguan (xingrenguanxue) */public class PrinterVar {    //该办法接管一个T类型的变量,打印并返回该变量    public <T> T print(T var) {        System.out.println(var);        return var;    }    public static void main(String[] args) {        PrinterVar printerVar = new PrinterVar();        String var = printerVar.print("aa");//String类型        Integer var1 = printerVar.print(12);//int类型        System.out.println(var + " " + var1);    }}

4. 对于我

点击这里意识我 。 (^o^)/