Java基础快速入门:泛型

如何快速深入学习 Java 的泛型? 哈喽,各位小伙伴们,你们好呀,我是喵手。运营社区:C站/掘金/腾讯云/阿里云/华为云/51CTO;欢迎大家常来逛逛 阅读详情

本文纲要

  1. 泛型概述
    不写泛型的弊端
    泛型的好处
  2. 泛型类的使用
    以ArrayList为例
    源码解析
  3. 自定义泛型类
    定义格式
    案例:Box类
  4. 泛型方法的使用
    ArrayList中的toArray方法
    空参 vs 带参
  5. 自定义泛型方法
    定义格式
    案例:批量添加元素
  6. 泛型接口
    定义格式
    两种使用方式
  7. 通配符
    无界通配符 <?>
    上界限定 <? extends 类型>
    下界限定 <? super 类型>
    示例项目结构

本文所有代码均位于 mygenericity 项目中,包结构如下:

mygenericity/src/com/wb/
├── genericitysummarize/
│   ├── GenericitySummarize.java 
│   └── GenericityClass.java 
├── genericityclass/
│   ├── Box.java 
│   └── MyGenericityClass.java 
├── genericitymethod/
│   ├── GenericityMethod1.java 
│   └── GenericityMethod2.java 
├── genericityinterface/
│   └── GenericityInterface.java 
└── genericityglobbing/
    └── genericityglobbing1.java 

泛型概述

在创建集合时,如果不指定泛型,集合中元素的类型会被当作 Object,虽然数据本身可以正常存储,但在取出时会丢失具体类型信息。

不写泛型的弊端演示:

public class GenericitySummarize {
    public static void main(String[] args) {
        ArrayList list = new ArrayList();      // 没有泛型 
        list.add("aaa");
        list.add("bbb");
        list.add("ccc");
        list.add(123);                        // 添加Integer也没问题 
 
        Iterator it = list.iterator();
        while (it.hasNext()) {
            // 取出时是Object,必须强转 
            String next = (String) it.next(); // 当取到123时会抛出ClassCastException 
            int len = next.length();
            System.out.println(len);
        }
    }
}

问题总结:
集合中可以随意添加不同类型数据(都是 Object)。
取出时必须强转,如果类型不一致,会在运行时抛出 ClassCastException。
代码冗余,所有需要强转的地方都得自己处理。

泛型的好处:

  1. 将运行时的错误提前到编译期(添加元素时就会类型检查)。
  2. 避免了强制类型转换,代码更简洁安全。

泛型类的使用

Java中已定义好的泛型类最典型的代表就是 ·ArrayList·。我们可以查看源码发现 ·ArrayList· 的声明:

public class ArrayList<E> extends AbstractList<E>
        implements List<E>, RandomAccess, Cloneable, java.io.Serializable { ... }

这里的 <E> 代表一个未知的类型,会在创建对象时被确定。

public class GenericityClass {
    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<>(); // 此时 E 被明确为 String 
        list.add("hello");
        String s = list.get(0); // 直接得到String,无需强转 
    }
}

ArrayList 中的 add(E e) 和 get(int index): E 等方法里的 E 都会随着创建对象时的具体类型参数而变化。这样设计让集合类可以适应任意数据类型,同时保证类型安全。

自定义泛型类

定义格式

修饰符 class 类名<泛型标识> { ... }

泛型标识可以是任意符合变量命名规则的字母,常见的有 E(Element)、T(Type)、K(Key)、V(Value)等。

案例:Box类

定义一个万能盒子,可以存放任意类型的元素:

// Box.java 
public class Box<E> {
    private E element;
 
    public E getElement() {
        return element;
    }
 
    public void setElement(E element) {
        this.element = element;
    }
}

使用方式:

// MyGenericityClass.java 
public class MyGenericityClass {
    public static void main(String[] args) {
        // 存放字符串 
        Box<String> box1 = new Box<>();
        box1.setElement("给小丽的土味情话");
        String element1 = box1.getElement();
        System.out.println(element1);
 
        // 存放整数 
        Box<Integer> box2 = new Box<>();
        box2.setElement(19);
        Integer element2 = box2.getElement();
        System.out.println(element2);
    }
}

在创建 Box 对象时,指定的类型会传递给类中的 E,从而使 element 和相应的 get/set 方法拥有具体的类型。

泛型方法的使用

Java内置的 ArrayList 就提供了泛型方法的典型应用:toArray。

public class GenericityMethod1 {
    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<>();
        list.add("给小花同学的土味情话");
        list.add("给小丽同学的土味情话");
        list.add("给小路同学的土味情话");
 
        // 空参:返回Object[]
        Object[] objects = list.toArray();
        System.out.println(Arrays.toString(objects));
 
        // 带参数的泛型方法:返回指定类型的数组 
        String[] strings = list.toArray(new String[list.size()]);
        System.out.println(Arrays.toString(strings));
    }
}

空参的 toArray() 返回的是 Object[],想使用字符串方法仍需强转。
带参的 toArray(T[] a) 会根据传入的数组类型返回相同类型的数组,避免了强转。
这里的 T 就是泛型方法中定义的类型参数。

自定义泛型方法

定义格式

修饰符 <泛型标识> 返回值类型 方法名(参数列表) { ... }

泛型标识必须声明在返回值之前,否则编译器会认为它是一个具体的类名。

案例:批量添加元素

定义一个可以批量添加四个元素到集合中并返回集合的方法:

public class GenericityMethod2 {
    public static void main(String[] args) {
        ArrayList<String> list1 = addElement(new ArrayList<String>(), "a", "b", "c", "d");
        System.out.println(list1);
 
        ArrayList<Integer> list2 = addElement(new ArrayList<Integer>(), 1, 2, 3, 4);
        System.out.println(list2);
    }
 
    // 泛型方法:类型T在调用时确定 
    public static <T> ArrayList<T> addElement(ArrayList<T> list, T t1, T t2, T t3, T t4) {
        list.add(t1);
        list.add(t2);
        list.add(t3);
        list.add(t4);
        return list;
    }
}

调用 addElement 时,根据传入的集合和元素类型自动推导出 T,无需手动指定。

泛型接口

定义格式

修饰符 interface 接口名<泛型标识> { ... }

两种使用方式

假设有如下泛型接口:

interface Genericity<E> {
    void method(E e);
}

方式一:实现类仍然不确定类型(延续泛型)

class GenericityImpl1<E> implements Genericity<E> {
    @Override 
    public void method(E e) {
        System.out.println(e);
    }
}
 
// 使用 
GenericityImpl1<String> genericity = new GenericityImpl1<>();
genericity.method("小丽给我的土味情话");

GenericityImpl1 本身也是一个泛型类,创建对象时才确定类型。

方式二:实现类直接指定具体类型

class GenericityImpl2 implements Genericity<Integer> {
    @Override 
    public void method(Integer integer) {
        System.out.println(integer);
    }
}
 
// 使用 
GenericityImpl2 genericityImpl2 = new GenericityImpl2();
genericityImpl2.method(19);

此时 GenericityImpl2 是一个普通类,类型被固定为 Integer。

通配符

通配符 ? 表示未知类型,常用于接收各种泛型集合,但不能添加元素(null除外)

1 ) 无界通配符 <?>

public static void printList(ArrayList<?> list) {
    for (Object obj : list) {
        System.out.println(obj);
    }
}

2 ) 上界限定 <? extends 类型>

表示可以接收该类型及其所有子类。例如 <? extends Number> 可以接收 Number 或 Integer、Double 等

3 ) 下界限定 <? super 类型>

表示可以接收该类型及其所有父类。例如 <? super Number> 可以接收 Number 或 Object。
完整案例

考虑继承关系:

Object

Number

Integer

代码演示:

public class genericityglobbing1 {
    public static void main(String[] args) {
        ArrayList<Integer> list1 = new ArrayList<>();
        ArrayList<Number> list2 = new ArrayList<>();
        ArrayList<Object> list3 = new ArrayList<>();
 
        // 上界通配符:接收 Number 及其子类 
        method1(list1);  // OK,Integer是Number的子类 
        method1(list2);  // OK 
        // method1(list3);  // 编译错误,Object不是Number的子类 
 
        // 下界通配符:接收 Number 及其父类 
        method2(list2);  // OK 
        method2(list3);  // OK,Object是Number的父类 
        // method2(list1);  // 编译错误,Integer不是Number的父类 
    }
 
    // 上界:只能是 Number 或 Number 的子类 
    public static void method1(ArrayList<? extends Number> list) {
        for (Number num : list) {
            System.out.println(num);
        }
    }
 
    // 下界:只能是 Number 或 Number 的父类 
    public static void method2(ArrayList<? super Number> list) {
        // 这里只能以Object类型访问,因为父类最低是Number,最高是Object 
        for (Object obj : list) {
            System.out.println(obj);
        }
    }
}

记忆要点:
? extends Number:规定了上边界,最多到 Number,所以只能取(当作 Number),不能随便添加。
? super Number:规定了下边界,至少是 Number,可以添加 Number 及其子类,但取出时只能当作 Object。

总结

泛型是Java提供的一种编译时类型安全检测机制,合理使用泛型可以写出更健壮、更优雅的代码。掌握泛型类、泛型方法、泛型接口以及通配符的用法,是Java基础的重要内容。

Java使用easyExcel生成excel文件直接写入邮件附件并发送 1.引入pom依赖 <!-- email --> <dependency> <groupId>javax.mail</groupId> <artifactId>mail</artifactId> <version>1.4.7</version> </dependency> <!-- easyexcel需要依赖poi jar包 --> <depe 阅读详情

相关推荐

PADS Layout中快速导入自定义元器件封装的实用技巧

本文详细介绍了在PADS Layout中高效导入自定义元器件封装的实用技巧。针对封装“找不到”、“对不上”、“导不进”三大痛点,系统梳理了从封装文件来源识别、库规划管理,到三种核心导入场景(从库文件添加、从其他设计借用、处理第三方格式)的完整操作流程,并提供了导入后的关键验证清单与常见问题排查方法,旨在帮助硬件工程师快速掌握这一提升设计效率的关键技能。

weixin_29302047的博客 375

JAVA基础:Java泛型编程快速入门

 JDK1.5 令我们期待很久,可是当他发布的时候却更换版本号为5.0。这说明Java已经有大幅度的变化。本文将讲解JDK5.0支持的新功能-----Java的泛型.  1、Java泛型  其实Java的泛型就是创建一个用类型作为参数的类。就象我们写类的方法一样,方法是这样的method(String str1,String str2 ),方法中参数str1、str2的值是可变的。而泛型也是一样的

sz_bdqn的专栏 659

华南理工大学电子与信息学院23年预推免复试面试经验贴

华南理工大学电子与信息学院23年预推免复试面试经验贴

Scut_Ty的博客 3299

快速入门java基础编程_Java基础:Java泛型编程快速入门

Java基础:Java泛型编程快速入门作者:文章来源:发布日期:2007年01月04日JDK1.5 令我们期待很久,可是当他发布的时候却更换版本号为5.0。这说明Java已经有大幅度的变化。本文将讲解JDK5.0支持的新功能-----Java的泛型.1、Java泛型其实Java的泛型就是创建一个用类型作为参数的类。就象我们写类的方法一样,方法是这样的method(String str1,S...

weixin_42140625的博客 150

2025 年第十五届 APMCM 亚太地区大学生数学建模竞赛A题 农业灌溉系统优化

该摘要探讨了农业灌溉系统优化面临的复杂挑战,涉及智能灌溉技术的应用与资源配置问题。研究聚焦于一个1公顷的方形农场案例,该农场种植三种作物并面临动态环境条件(土壤类型、气象变化)。系统优化需平衡河流引水(非线性成本函数:C=50L^1.2+0.1Q^1.5)与储水罐灌溉(成本5元/升容积)两种方案,同时满足喷灌技术约束(喷头间距≥15米,覆盖半径15米)。关键矛盾体现在"平河旱储"的水资源调配策略与多作物需水量差异之间的协调,需通过传感器数据实时调整灌溉方案以实现效率最大化。(149字)

m0_60472361的博客 643

基于Java的高校校园点餐系统

本文介绍了一个基于Java技术开发的高校校园点餐系统,该系统以B/S结构为基础,采用MySQL作为数据库,实现了一个高效、便捷的在线点餐平台。系统主要面向三类用户:管理员、用户和食堂工作人员,提供包括用户管理、食堂管理、菜单管理、订单管理等在内的多项功能。通过系统的具体测试,验证了其可行性和有效性,为高校师生提供了一个科学化、系统化的点餐服务。高校校园点餐系统的开发和实现,不仅提高了校园餐饮服务的效率和质量,也为师生提供了一个更加便捷的点餐体验。

a632341031的博客 841

Java基础:Java泛型编程快速入门

1、Java泛型 其实Java的泛型就是创建一个用类型作为参数的类。就象我们写类的方法一样,方法是这样的method(String str1,String str2 ),方法中参数str1、str2的值是可变的。而泛型也是一样的,这样写class Java_Generics<K,V>,这里边的K和V就象方法中的参数str1和str2,也是可变。下面看看例子: //code list 1 impor

Java的专栏 671

Apache NiFi新手必看:从零开始的数据流设计入门教程(含实战案例)

本文为Apache NiFi新手提供从零开始的数据流设计入门指南。通过实战案例,详细讲解了如何利用这一强大的数据采集工具,以可视化拖拽方式构建自动化数据流,实现从文件监控、内容处理到数据入库的全流程,并涵盖核心概念、环境搭建及生产环境调优要点。

weixin_29066781的博客 149

小白零基础快速入门Java —— 第八课:面向对象高级篇之泛型

小白零基础快速入门Java —— 第八课:面向对象高级篇之泛型。本文介绍了以下内容:1、泛型的概念。2、泛型类。3、泛型接口。4、泛型方法、泛型通配符和上下限。5、泛型的注意事项:擦除问题、基本数据类型问题。

Huacyu的博客 107

19、CATIA V5:参数化建模与零件目录创建全解析

本文详细解析了在CATIA V5中通过设计表实现参数化建模及零件目录创建的完整流程。以支撑块和钩形夹为例,介绍了参数识别、设计表创建与关联、配置管理以及零件目录的构建方法。同时,提供了实际操作建议和注意事项,帮助设计师高效创建和管理零件族,提升设计效率和质量。

raspberrypi5的博客 449

[QMT量化交易小白入门]-三十五、如何将聚宽策略信号转为QMT实盘交易

Flask是一个轻量级的Web应用框架,它提供了简单而灵活的方式来构建Web应用程序。在本案例中,将使用Flask来搭建一个本地服务,用于监听来自jq2qmt.py脚本的交易信号,并根据信号执行相应的下单操作。

木头大左的博客 2696

【编程语言】Kotlin快速入门 - 泛型

Java工程师Kotlin快速入门之泛型

XuanRan的博客 5024

【调优】OpenClaw调优之模型(tokens)篇

OpenClaw用户常遇四大痛点:规则被无视、API账单暴涨、低效模型选择、记忆丢失。通过/context list命令可解析上下文组成,包括工作区配置、引导参数限制、系统提示词等关键信息。重点需关注Token消耗来源,如核心配置文件、技能工具说明等,避免静默截断。建议精简非必要内容,优化记忆机制,平衡功能与成本。该分析帮助用户减少无效操作,合理控制API支出。

海兰 991

通过案例快速理解JAVA泛型

一、上栗子 ​ 啥都不说先上例子:定义一个Show方法,实现一个“弱智”的功能,输出传入的参数值。 先来考虑传入的是一个int类型参数,秒写下面代码: public static void Show(int param){//为了能在main方法中调用,定义为static,知识点:静态方法调用 System.out.println(param); } //main方法如下 public static void main(String[] args) { Show(123); //调用static方法,输

cqzhongj的博客 1149

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

Java 中的泛型详解

泛型,即“参数化类型”。一提到参数,最熟悉的就是定义方法时有形参列表,普通方法的形参列表中,每个形参的数据类型是确定的,而变量是一个参数。在调用普通方法时需要传入对应形参数据类型的变量(实参),若传入的实参与形参定义的数据类型不匹配,则会报错。那参数化类型是什么?以方法的定义为例,在方法定义时,将方法签名中的形参的数据类型也设置为参数(也可称之为类型参数),在调用该方法时再从外部传入一个具体的数据类型和变量。

XuChaofafa的博客 1704

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

java中的泛型

本文详细的介绍了java中的泛型,包括泛型的定义,泛型的使用以及注意事项

weixin_74200123的博客 1001

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

Java泛型

对Java泛型学习的一点心得

weixin_57473640的博客 1096

JAVA快速入门-泛型

转载自 http://blog.youkuaiyun.com/itdo_just https://blog.youkuaiyun.com/itdo_just/article/details/79328549 泛型是程序设计语言的一种特性。允许程序员在强类型程序设计语言中编写代码时定义一些可变部分,那些部分在使用前必须作出指明。各种程序设计语言和其编译器、运行环境对泛型的支持均不一样。将类型参数化以达到代...

拼搏的小白 328

Java泛型总结一 为什么使用泛型

快速了解泛型 1泛型可以使用在类或者方法上。 2泛型是一种约束,把握住了入口(通过强制类型检查来实现)和出口(通过自动类型转换来实现)。 3泛型是一种占位符或者说模板,在编码时把一个变量由具体化变成了抽象化,增加了代码的灵活度。 4泛型只在编译时起作用,编译之后可以理解为就是一个Object类型,在运行时可以通过反射操作绕过泛型的限制,传入不同的类型。 5泛型定义虽然可以约束声明时传入的参数类型...

编程人生 1937

Java 泛型详解

全网最详细最权威的Java泛型知识讲解。带大家深入浅出的了解泛型相关知识以及结合本人公司大佬的问题带大家深入泛型

CodeSuc 的技术博客 843

Java快速入门集合框架和泛型图解(少代码,多图解,快速掌握Java数据结构)——Java基础系列

本文只是面向入门级的基础概念解读,包含快速使用讲解,代码少关键多,主要是读起来不累 ——尽管不具备真正深入的难点,图例丰富,通俗易懂,适合新手小白入门。

代码之狐的博客 899

Java泛型编程快速入门

Java泛型编程快速入门 JDK1.5 令我们期待很久,可是当他发布的时候却更换版本号为5.0。这说明Java已经有大幅度的变化。本文将讲解JDK5.0支持的新功能-----Java的泛型. 1、Java泛型 其实Java的泛型就是创建一个用类型作为参数的类。就象我们写类的方法一样,方法是这样的method(String str1,String str2 ...

diaoyinji6441的博客 122

scala快速入门系列【泛型】

        本篇作为scala快速入门系列的第三十五篇博客,为大家带来的是关于泛型的内容。 文章目录泛型定义一个泛型方法泛型类上下界上界下界协变、逆变、非变非变协变逆变 泛型         scala和Java一样,类和特质、方法都...

大数据梦想家 2486

java泛型

基本语法:class 类名<T, R...>{...表示可以有多个泛型R r;T t;...注意细节使用泛型的数组不能初始化, 不能确定泛型的类型, 无法开辟空间T[] ts = new T[8];//会报错静态的方法中不能使用类的泛型: 因为静态方法是在对象创建之前,加载类的时候进行加载如果在创建对象时没有指定类型, 那就默认为Object泛型接口的类型, 在继承接口或者实现接口时确定其他与泛型类类似泛型方法,可以定义在普通类中, 也可以定义在泛型类中。

2301_79004249的博客 1543

Java 中的包装类和泛型

Java 中的 包装类 和 泛型

Yuan_o_的博客 1270
上一篇: Java基础快速入门: List集合、数据结构与源码解析
下一篇: Java基础快速入门: Set集合与TreeSet详解
Wang's Blog
博客等级 码龄12年 7434粉丝 2421原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Wang's Blog

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值