我的编程空间,编程开发者的网络收藏夹
学习永远不晚

Java泛型怎么应用

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

Java泛型怎么应用

本篇内容主要讲解“Java泛型怎么应用”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Java泛型怎么应用”吧!

一、什么是泛型

Java 泛型(generics)是 JDK 5 中引入的一个新特性, 泛型提供了编译时类型安全检测机制,该机制允许程序员在编译时检测到非法的类型。

Java泛型怎么应用

简单理解就是:泛型指定编译时的类型,减少运行时由于对象类型不匹配引发的异常。其主要用途是提高我们的代码的复用率。

我们Java标准库中的ArrayList就是泛型使用的典型应用:

public class ArrayList extends AbstractList implements List, RandomAccess, Cloneable, java.io.Serializable {            ......   public ArrayList(Collection c) {       elementData = c.toArray();       if ((size = elementData.length) != 0) {           // c.toArray might (incorrectly) not return Object[] (see 6260652)           if (elementData.getClass() != Object[].class)               elementData = Arrays.copyOf(elementData, size, Object[].class);       } else {           // replace with empty array.           this.elementData = EMPTY_ELEMENTDATA;       }   }   public void sort(Comparator c) {       final int expectedModCount = modCount;       Arrays.sort((E[]) elementData, 0, size, c);       if (modCount != expectedModCount) {           throw new ConcurrentModificationException();       }       modCount++;   }    .....   public E get(int index) {       rangeCheck(index);       return elementData(index);   }   public boolean add(E e) {       ensureCapacityInternal(size + 1);  // Increments modCount!!       elementData[size++] = e;       return true;   }}

源码中,ArrayList中的E称为类型参数变量,而整个ArrayList我们称为泛型类型。 我们可以指定除基本类型之外的任何类型,如:ArrayList。

源码中Collection 中? 通配符类型 表示类型的上界,表示参数化类型的可能是T 或是 T的子类。

源码中Comparator 表示类型下界(Java Core中叫超类型限定),表示参数化类型是此类型的超类型(父类型),直至Object。

二、extends和super通配符

在定义泛型类型Generic的时候,也可以使用extends通配符来限定T的类型:

public class Generic { ... }

现在,我们只能定义:

Generic p1 = null;Generic p2 = new Generic(1, 2);Generic p3 = null;

因为Number、Integer和Double都符合。

非Number类型将无法通过编译:

Generic p1 = null; // compile error!Generic

因为String、Object都不符合,因为它们不是Number类型或Number的子类。

我们看一个例子:

public class Test {   static class Food {   }   static class Fruit extends Food {   }   static class Apple extends Fruit {   }   static class Orange extends Fruit {   }   public void testExtend() {       List list = new ArrayList();       //无法安全添加任何具有实际意义的元素,报错,extends为上界通配符,只能取值,不能放.       //因为Fruit的子类不只有Apple还有Orange,这里不能确定具体的泛型到底是Apple还是Orange,所以放入任何一种类型都会报错       //list.add(new Apple());       //list.add(new Orange());       //可以添加null,因为null可以表示任何类型       list.add(null);       //可以正常获取,用java多态       Food foot = list.get(0);       Apple apple = (Apple) list.get(0);   }   public void testSuper() {       List list = new ArrayList();       //super为下界通配符,可以存放元素,但是也只能存放当前类或者子类的实例,以当前的例子来讲,       list.add(new Fruit());       list.add(new Apple());       //无法确定Fruit的父类是否只有Food一个(Object是超级父类)       //因此放入Food的实例编译不通过,只能放自己的实例 或者根据java多态的特性放子类实例       //list.add(new Food());       //List list2 = new ArrayList();       //Fruit fruit = list.get(0); //不能确定返回类型   }}

在testExtend方法中,因为泛型中用的是extends,在向list中存放元素的时候,我们并不能确定List中的元素的具体类型,即可能是Apple也可能是Orange。因此调用add方法时,不论传入new Apple()还是new Orange(),都会出现编译错误。

理解了extends之后,再看super就很容易理解了,即我们不能确定testSuper方法的参数中的泛型是Fruit的哪个父类,因此在调用get方法时只能返回Object类型。结合extends可见,在获取泛型元素时,使用extends获取到的是泛型中的上边界的类型(本例子中为Fruit),范围更小。

总结:

在使用泛型时,存取元素时用super。

获取元素时,用extends。

有了上面的结论我们看下Java标准库的Collections类定义的copy()方法,这个copy()方法的定义就完美地展示了extends和super的意图:

copy()方法内部不会读取dest,因为不能调用dest.get()来获取T的引用;

copy()方法内部也不会修改class="lazy" data-src,因为不能调用class="lazy" data-src.add(T)。

public class Collections {   // 把class="lazy" data-src的每个元素复制到dest中:   public static  void copy(List dest, List class="lazy" data-src) {       for (int i=0; i

三、泛型擦除

Java的泛型是伪泛型,这是因为Java在编译期间,所有的泛型信息都会被擦掉,正确理解泛型概念的首要前提是理解类型擦除。Java的泛型基本上都是在编译器这个层次上实现的,在生成的字节码中是不包含泛型中的类型信息的,使用泛型的时候加上类型参数,在编译器编译的时候会去掉,这个过程成为类型擦除

我们看一个示例:

public class Test2 {   public static void main(String[] args) {       Map map = new HashMap();       Animal animal = new Animal();       animal.setVegetarian(true);       animal.setEats("fish");       map.put("cat", animal);       String json = new Gson().toJson(map);       System.out.println(json);       Map jsonToMap = fromJson(json);       System.out.println(jsonToMap);       Animal animal1 = jsonToMap.get("cat");       System.out.println(animal1.getEats());   }   public static  T fromJson(String str) {       return new Gson().fromJson(str, new TypeToken() {       }.getType());   }}

上的代码运行会提示如下异常:

Exception in thread "main" java.lang.ClassCastException: com.google.gson.internal.LinkedTreeMap cannot be cast to com.uaf.rabbitmq.producer.Animal   at com.uaf.rabbitmq.producer.Test2.main(Test2.java:30)

异常原因主要是这句:new Gson().fromJson(str, new TypeToken() {}.getType());

这句在实际执行的时候,List中的T并未传入实际的泛型参数,导致Gson按照LinkedTreeMap来解析JSON,以致发生了错误;这就是一个在编译期泛型类型擦除所导致的问题;

解决这个问题我们需要修改fromJson方法

public class Test2 {   public static void main(String[] args) {       Map map = new HashMap();       Animal animal = new Animal();       animal.setVegetarian(true);       animal.setEats("fish");       map.put("cat", animal);       String json = new Gson().toJson(map);       System.out.println(json);       Map jsonToMap = fromJson(json,         new TypeToken>() {}.getType());       System.out.println(jsonToMap);       Animal animal1 = jsonToMap.get("cat");       System.out.println(animal1.getEats());   }   public static  T fromJson(String str, Type type) {       return new Gson().fromJson(str, type);   }}

在Gson中提供了TypeToken解决泛型运行时类型擦除问题,TypeToken 这个类来帮助我们捕获像Map这样的泛型信息。上文创建了一个匿名内部类,这样Java编译器就会把泛型信息编译到这个匿名内部类里,然后在运行时就可以被getType()方法用反射API提取到。

到此,相信大家对“Java泛型怎么应用”有了更深的了解,不妨来实际操作一番吧!这里是编程网网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

Java泛型怎么应用

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

Java泛型怎么应用

本篇内容主要讲解“Java泛型怎么应用”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Java泛型怎么应用”吧!一、什么是泛型Java 泛型(generics)是 JDK 5 中引入的一个新特性,
2023-06-27

Java中的泛型怎么应用

本篇内容介绍了“Java中的泛型怎么应用”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!泛型概述泛型在java中有很重要的地位,在面向对象编程
2023-06-02

如何使用 Java 泛型类和泛型方法?(java泛型类和泛型方法怎么使用)

在Java编程中,泛型是一种强大的特性,它允许我们编写可以处理不同类型对象的代码,而无需为每种类型编写重复的代码。泛型类和泛型方法是Java泛型的两个重要组成部分,下面我们将详细介绍它们的使用方法。一、泛型类的使用泛型类
如何使用 Java 泛型类和泛型方法?(java泛型类和泛型方法怎么使用)
Java2024-12-18

java泛型类怎么使用

本篇内容介绍了“java泛型类怎么使用”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!1、语法 类名<具体的数据类型> 对象名=new 类名
2023-07-06

如何理解 Java value 在泛型中的应用?(Java value在泛型中的应用)

在Java编程中,泛型是一种强大的特性,它允许我们编写更加通用、类型安全的代码。其中,value在泛型中的应用是一个重要的概念。一、泛型的基本概念泛型是JDK5引入的一个特性,它允许在定义类、
如何理解 Java value 在泛型中的应用?(Java value在泛型中的应用)
Java2024-12-16

怎么用Java泛型实现类型擦除

本篇内容主要讲解“怎么用Java泛型实现类型擦除”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“怎么用Java泛型实现类型擦除”吧!前言先给大家奉上一道经典的测试题。List l1
2023-06-29

Java Scala泛型方法怎么使用

本文小编为大家详细介绍“Java Scala泛型方法怎么使用”,内容详细,步骤清晰,细节处理妥当,希望这篇“Java Scala泛型方法怎么使用”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。1. 泛型泛型的意思是
2023-07-05

java泛型通配符怎么使用

Java泛型通配符用于表示未知类型。在泛型类、接口和方法中使用通配符可以使其具有更大的灵活性。通配符有三种使用方式:1. 上界通配符(? extends 类型):表示接受类型参数为类型或其子类的对象。```javapublic void p
2023-09-16

怎么理解Java/Scala泛型

本篇内容介绍了“怎么理解Java/Scala泛型”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!泛型(Generics)是强类型编程语言中经常
2023-06-16

Java中怎么擦除泛型类型

Java中怎么擦除泛型类型,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。前言Java泛型这个特性是从JDK 1.5才开始加入的,因此为了兼容之前的版本,Java泛型的实现采
2023-06-20

Java泛型该怎么掌握

这篇文章主要介绍“Java泛型该怎么掌握”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“Java泛型该怎么掌握”文章能帮助大家解决问题。数据类型转换和错误为理解泛型类型为何如此有用,我们要将注意力转向
2023-06-03

如何利用 java 泛型来实现排序?(怎么使用java泛型实现排序)

在Java编程中,泛型是一种强大的特性,它允许我们编写更通用、类型安全的代码。其中,使用Java泛型实现排序是一个常见的需求,本文将详细介绍如何使用Java泛型来实现排序。一、泛型的基本概念泛型是JDK5.0引
如何利用 java 泛型来实现排序?(怎么使用java泛型实现排序)
Java2024-12-18

如何定义 Java 泛型函数?(java泛型函数怎么定义)

在Java编程中,泛型是一种强大的特性,它允许我们编写可以处理不同类型对象的代码,提高代码的复用性和类型安全性。其中,定义泛型函数是使用泛型的重要方面之一。本文将详细介绍如何定义Java泛型函数。一、泛型的基本概念泛型是
如何定义 Java 泛型函数?(java泛型函数怎么定义)
Java2024-12-19

怎么在java中使用泛型接口

怎么在java中使用泛型接口?针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。常用的java框架有哪些1.SpringMVC,Spring Web MVC是一种基于Java的实
2023-06-14

Java中泛型有什么用

这篇文章主要介绍了Java中泛型有什么用,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。泛型1、简单泛型泛型的主要目的之一就是用来指定容器要持有什么类型的对象,而且由编译器来保
2023-06-20

如何在 Java 中获取泛型的类型?(java怎么获取泛型的类型)

在Java编程中,泛型是一种强大的特性,它允许我们编写更通用、类型安全的代码。然而,对于一些开发者来说,获取泛型的类型可能会是一个挑战。本文将详细介绍在Java中如何获取泛型的类型。一、泛型的基本概念泛型是Java5
如何在 Java 中获取泛型的类型?(java怎么获取泛型的类型)
Java2024-12-17

TypeScript 泛型怎么用

这篇文章主要为大家展示了“TypeScript 泛型怎么用”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“TypeScript 泛型怎么用”这篇文章吧。1.简单的使用现在我们要定义一个join函数
2023-06-22

Java中的泛型怎么理解

本篇内容介绍了“Java中的泛型怎么理解”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!泛型:是JDK5中引入的特性,可以在编译阶段约束操作的
2023-06-30

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录