Java不可不知的泛型使用示例代码

网友投稿 263 2022-11-28


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是数组中元素的数量。add和get方法能添加和获取元素。

下面测试一下:

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);

//以上正常tJGJrArye运行

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 IndexOutOfBoundsExceptiontJGJrArye("数组已满");

}

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变量接收,报错

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

有!用泛型!

2. 泛型类

使用泛型改造MyArrayList:

/**

* @author Xing Xiaoguan (xingrenguanxue)

*/

public class MyArrayList {

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 myArrayList = new MyArrayList<>(4);

myArrayList.add(111); //向数组中添加3个int元素

// myArrayLihttp://st.add("222"); //添加非Integer元素报错

int i = myArrayList.get(1); //无需强制转型

System.out.println(i);

}

}

经过改造,我们把MyArrayList类改为了一个泛型类,它是一个具有多个类型变量的类。

泛型类的声明方式:引入一个类型变量,如T,然后使用<>将其括起来,放在类名后。

public class MyArrayList {

//......

}

如何理解类型变量?它就类似于数学中函数中的变量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 {

//......

}

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

MyArrayList myArrayList = new MyArrayList<>(4);

该过程就相当于向数学函数中代入数值:

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

3. 泛型方法

当我们声明了一个泛型类后,可以很自然地在类内部使用泛型方法。

其实,当类是普通类时,我们仍然能够使用泛型方法。下面是一个例子:

/**

* @author Xing Xiaoguan (xingrenguanxue)

*/

public class PrinterVar {

//该方法接收一个T类型的变量,打印并返回该变量

public 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);

}

}


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:SpringBoot 集成 Jasypt 对数据库加密以及踩坑
下一篇:浅析IDEA如何正确配置Gradle? GRADLE_USER_HOME 和 Gradle user home的区别
相关文章

 发表评论

暂时没有评论,来抢沙发吧~