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

 更新时间:2020年08月08日 08:41:33   作者:行人观学  
这篇文章主要介绍了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);
 }
}

到此这篇关于Java不可不知的泛型使用的文章就介绍到这了,更多相关Java 泛型使用内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Java多线程之悲观锁与乐观锁

    Java多线程之悲观锁与乐观锁

    这篇文章主要为大家详细介绍了Java悲观锁与乐观锁,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助
    2022-03-03
  • 详解Java的线程状态

    详解Java的线程状态

    本文主要为大家详细介绍一下Java的线程状态,文中的示例代码讲解详细,对我们学习有一定的帮助,感兴趣的小伙伴可以跟随小编学习一下
    2022-11-11
  • SpringBoot整合MQTT并实现异步线程调用的问题

    SpringBoot整合MQTT并实现异步线程调用的问题

    这篇文章主要介绍了基于SpringBoot通过注解实现对mqtt消息处理的异步调用,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-11-11
  • Java OpenSSL生成的RSA公私钥进行数据加解密详细介绍

    Java OpenSSL生成的RSA公私钥进行数据加解密详细介绍

    这篇文章主要介绍了Java OpenSSL生成的RSA公私钥进行数据加解密详细介绍的相关资料,这里提供实例代码及说明具体如何实现,需要的朋友可以参考下
    2016-12-12
  • Java实战项目练习之球馆在线预约系统的实现

    Java实战项目练习之球馆在线预约系统的实现

    理论是远远不够的,只有在实战中才能获得能力的提升,本篇文章手把手带你用java+SpringBoot+maven+freemark+Mysql实现一个球馆在线预约系统,大家可以在过程中查缺补漏,提升水平
    2022-01-01
  • springboot集成WebSockets广播消息(推荐)

    springboot集成WebSockets广播消息(推荐)

    这篇文章主要介绍了springboot-集成WebSockets广播消息,本文给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下
    2019-12-12
  • SpringBoot整合Ldap的实现示例

    SpringBoot整合Ldap的实现示例

    本文主要介绍了SpringBoot整合Ldap的实现示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-11-11
  • 基于Java实现一个简单的图片加载器

    基于Java实现一个简单的图片加载器

    这篇文章主要为大家详细介绍了如何使用Java 2D API(Java的绘图和图像API)来实现图片加载和显示,文中的示例代码讲解详细,需要的小伙伴可以参考一下
    2023-11-11
  • Spring源码阅读MethodInterceptor解析

    Spring源码阅读MethodInterceptor解析

    这篇文章主要为大家介绍了Spring源码阅读MethodInterceptor使用示例解析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-11-11
  • 用Java实现希尔排序的示例

    用Java实现希尔排序的示例

    问题:现有一段程序S,可以对任意n个数进行排序。如果现在需要对n^2个数进行排序,最少需要调用S多少次?只允许调用S,不可以做别的操作。我们用希尔排序来做解决这个
    2013-11-11

最新评论