前面的文章:java
本文介绍了Java的泛型的基本使用。数组
看下面一个例子:ide
为了说明问题,本类写的尽可能简陋,请把目光主要放在类型上。函数
/** * @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
是数组中元素的数量。add
和get
方法能添加和获取元素。测试
下面测试一下:code
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
。若是场景继续变怎么办?那就再写一份新代码!ci
这样太麻烦了!有没有解决办法?有!
咱们知道,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); } }
发现能够向数组中添加和获取int
或String
类型的元素,这证实该类的数组和方法同时对各类类型的数据都有用,没必要再添加额外代码。
可是这样又出现了两个问题:
第一:从数组中获取元素时,须要强制转换类型才行。
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变量接收,报错
那这个问题有没有解决办法呢?
有!用泛型!
使用泛型改造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
当咱们声明了一个泛型类后,能够很天然地在类内部使用泛型方法。
其实,当类是普通类时,咱们仍然可以使用泛型方法。下面是一个例子:
/** * @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); } }
点击这里认识我 。 (^o^)/