千家信息网

Java泛型怎么应用

发表于:2026-11-01 作者:千家信息网编辑
千家信息网最后更新 2026年11月01日,本篇内容主要讲解"Java泛型怎么应用",感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习"Java泛型怎么应用"吧!一、什么是泛型Java 泛型(generic
千家信息网最后更新 2026年11月01日Java泛型怎么应用

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

一、什么是泛型

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

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

我们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()方法内部也不会修改src,因为不能调用src.add(T)。

public class Collections {   // 把src的每个元素复制到dest中:   public static  void copy(List dest, List 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泛型怎么应用"有了更深的了解,不妨来实际操作一番吧!这里是网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!

类型 编译 方法 元素 参数 子类 时候 通配符 应用 信息 实例 实际 例子 就是 源码 编译器 问题 运行 多态 安全 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 深圳市人人互联网科技有限公司 南京欣网互联网络科技有限公司 今日互联网科技 腾讯阿里互联网科技 广州互联网科技公司 以房互联网科技 互联网金融科技平台 互联网科技上市公司 兼蜜互联网科技 深圳卡尔迅互联网科技有限公司怎么样 字节跳动和互联网科技 贵州叶脉互联网科技有限公司所属行业 互联网科技有哪些公司 崇明区互联网教育科技诚信经营 阿里互联网科技企业 互联网数据科技专业 南博望互联网科技有限公司 有人说阿里系是互联网科技企业 互联网科技包装股 好易买互联网科技 互联网科技巨头监管 互联网科技logo设计 玖二柒互联网科技公司待遇 西藏七维空间互联网科技有限公司 互联网保险科技创业 朱啸虎曾投资哪些互联网科技企业 上海科技产业互联网平台 江苏苏星互联网科技有限公司 互联网科技融合创新 北京品多多互联网科技有限公司
0