码农知识堂 - 1000bd
  •   Python
  •   PHP
  •   JS/TS
  •   JAVA
  •   C/C++
  •   C#
  •   GO
  •   Kotlin
  •   Swift
  • Java中的泛型讲解【最详细】【精美版】


     可以看下我亲自录制的视频讲解: 

       【布道者】Ep_集合-泛型_哔哩哔哩_bilibili

        点我进入

          

    问题

    在前面学习集合时,我们都知道集合中是可以存放任意对象的,只要把对象存储集合后,那么这时他们都会被提升成Object类型。当我们在取出每一个对象,并且进行相应的操作,这时必须采用类型转换。

    看如下的代码:

    1. public class GenericDemo {
    2. public static void main(String[] args) {
    3. Collection coll = new ArrayList();
    4. coll.add("无鸡");
    5. coll.add("无忌");
    6. coll.add(5);//由于集合没有做任何限定,任何类型都可以给其中存放
    7. Iterator it = coll.iterator();
    8. while(it.hasNext()){
    9. //需要打印每个字符串的长度,就要把迭代出来的对象转成String类型
    10. String str = (String) it.next();
    11. System.out.println(str.length());
    12. }
    13. }
    14. }

    程序在运行时发生了问题java.lang.ClassCastException。

    为什么会发生类型转换异常呢?

             分析下:由于集合中什么类型的元素都可以存储。导致取出时强转引发运行ClassCastException。

    怎么来解决这个问题呢?

    Collection虽然可以存储各种对象,但实际上通常Collection只存储同一类型对象。例如都是存储字符串对象。

    • 泛型:可以在类或方法中预支地使用未知的类型。

    tips:一般在创建对象时,将未知的类型确定具体的类型。当没有指定泛型时,默认类型为Object类型。

    详细概述

    是JDK5中引入的特性,它提供了编译时类型安全检测机制,该机制允许在编译时检测到非法的类型。

    分为泛型类、泛型方法、泛型接口。

    泛型的好处

    那么泛型带来了哪些好处呢?

    • 将运行时期的ClassCastException,转移到了编译时期变成了编译失败。

    • 避免了类型强转的麻烦。

    通过我们如下代码体验一下:

    1. public class GenericDemo2 {
    2. public static void main(String[] args) {
    3.        Collection list = new ArrayList();
    4.        list.add("无鸡");
    5.        list.add("无忌");
    6.         list.add(5);//当集合明确类型后,存放类型不一致就会编译报错
    7.        // 集合已经明确具体存放的元素类型,那么在使用迭代器的时候,迭代器也同样会知道具体遍历元素类型
    8.        Iterator it = list.iterator();
    9.        while(it.hasNext()){
    10.            String str = it.next();
    11.            //当使用Iterator控制元素类型后,就不需要强转了。获取到的元素直接就是String类型
    12.            System.out.println(str.length());
    13.       }
    14. }
    15. }

    泛型的定义与使用

    说明

    我们在集合中会大量使用到泛型

    泛型,用来灵活地将数据类型应用到不同的类、方法、接口当中。将数据类型作为参数进行传递。

    泛型类

    格式:

    修饰符 class 类名<代表泛型的变量> {  }

    Collection接口集合:

    1. interface Collection{
    2.    public boolean add(E e){ }
    3.   ...
    4. }

    使用泛型: 即什么时候确定泛型。

    在创建对象的时候确定泛型

    例如,Collection list = new ArrayList();

    此时,变量E的值就是String类型,那么我们的类型就可以理解为:

    1. interface Collection{
    2.     public boolean add(String e){
    3.    
    4.     }
    5.     ...
    6. }

    自定义泛型类:

    1. public class Generic {
    2.    private T t;
    3.    public T getT() {
    4.        return t;
    5.   }
    6.    public void setT(T t) {
    7.        this.t = t;
    8.   }
    9. }

    测试类:

    1. public class Demo {
    2.    public static void main(String[] args) {
    3.        Generic g1 = new Generic();
    4.        g1.setT("ikun");
    5.        System.out.println(g1.getT());
    6.        
    7.        Generic g2 = new Generic();
    8.        g2.setT(30);
    9.        System.out.println(g2.getT());
    10.        
    11.        Generic g3 = new Generic();
    12.        g3.setT(true);
    13.        System.out.println(g3.getT());
    14.   }
    15. }

    泛型方法

    格式:

    修饰符 <代表泛型的变量> 返回值类型 方法名(参数){  }

    案例:

    1. public class Generic {
    2.    public void show(T t) {
    3.        System.out.println(t);
    4.   }
    5. }

    测试类:

    1. public class GenericDemo {
    2.    public static void main(String[] args) {
    3.        Generic g = new Generic();
    4.        g.show("无忌");
    5.        g.show(29);
    6.        g.show(true);
    7.   }
    8. }

    泛型接口

    格式:

    修饰符 interface 接口名<类型> { }

    示例:

    1. public interface Generic {
    2.    void show(T t);
    3. }

    泛型接口实现类:

    1. public class GenericImpl implements Generic {
    2.    @Override
    3.    public void show(T t) {
    4.        System.out.println(t);
    5.   }
    6. }

    测试类:

    1. public class GenericDemo {
    2.    public static void main(String[] args) {
    3.        Generic g1 = new GenericImpl();
    4.        g1.show("无忌");
    5.        
    6.        Generic g2 = new GenericImpl();
    7.        g2.show(30);
    8.   }
    9. }

    泛型通配符

    说明

    当使用泛型类或者接口时,传递的数据中,泛型类型不确定,可以通过通配符表示。但是一旦使用泛型的通配符后,只能使用Object类中的共性方法,集合中元素自身方法无法使用。

    通配符基本使用

    泛型的通配符:不知道使用什么类型来接收的时候,此时可以使用?,?表示未知通配符。

    代码理解如下:

    1. public static void main(String[] args) {
    2.    Collection list1 = new ArrayList();
    3.    getElement(list1);
    4.    Collection list2 = new ArrayList();
    5.    getElement(list2);
    6. }
    7. ​
    8. public static void getElement(Collection coll){//只能放Integer,不能放String
    9.    
    10. }
    11. ​
    12. public static  void getElement(Collection coll){
    13.    
    14. }
    15. ​

    1、通配符,代表未知类型,代表不关心或无法确定实际操作的类型,一般与容器类配合使用。

    1. public void testV(List list) {
    2.  
    3. }

    高级使用

    说明

    之前设置泛型的时候,实际上是可以任意设置的,只要是类就可以设置。但是在JAVA的泛型中可以指定一个泛型的上限和下限

    上限

    • 格式: 类型名称 对象名称

    • 意义: 只能接收该类型及其子类

    下限

    • 格式: 类型名称 对象名称

    • 意义: 只能接收该类型及其父类型

    案例

    比如:现已知Object类,String 类,Number类,Integer类,其中Number是Integer的父类

    1. class Parent{
    2.    String name;
    3. }
    4. ​
    5. class Son extends Parent{
    6.    int age;
    7. }
    8. public static void main(String[] args) {
    9.    Collection list1 = new ArrayList();
    10.    Collection list2 = new ArrayList();
    11.    Collection list3 = new ArrayList();
    12.    
    13.    getElement1(list1);
    14.    getElement1(list2);
    15.    getElement1(list3);//报错
    16.  
    17.    getElement2(list1);
    18.    getElement2(list2);//报错
    19.    getElement2(list3);
    20.  
    21. }
    22. ​
    23. ​
    24. // 泛型的上限:此时的泛型?,必须是Parent类型或者Parent类型的子类
    25. public static void getElement1(Collection coll){
    26.    
    27. }
    28. // 泛型的下限:此时的泛型?,必须是Parent类型或者Parent类型的父类
    29. public static void getElement2(Collectionsuper Parent> coll){
    30.    
    31. }
    32. 谢谢观看啦  不懂可以看我的视频讲解

    33. 相关阅读:
      GPTZero:论文打假神器
      通信原理学习笔记3-4:数字通信系统性能指标(带宽、信噪比Eb/N0、可靠性与误码率、有效性与频谱利用率)
      【C++】-- 哈希算法
      Composer交互文档如何在PPT当中使用
      Linux内核完全注释(基于Linux0.11)_笔记_Linux0.11执行流程
      自动化工具:PyAutoGUI的鼠标与键盘控制,解放双手的利器
      鸿蒙HarmonyOS实战-ArkUI组件(RelativeContainer)
      几种常见的 MySQL/PolarDB-MySQL 回收表空间方法对比
      Uniapp 图片选择插件(支持视频、音频) Ba-MediaPicker
      探索互联世界的灯光艺术:FastLED库详细介绍及应用实例
    34. 原文地址:https://blog.csdn.net/weixin_45434902/article/details/127136199
      • 最新文章
      • 攻防演习之三天拿下官网站群
        数据安全治理学习——前期安全规划和安全管理体系建设
        企业安全 | 企业内一次钓鱼演练准备过程
        内网渗透测试 | Kerberos协议及其部分攻击手法
        0day的产生 | 不懂代码的"代码审计"
        安装scrcpy-client模块av模块异常,环境问题解决方案
        leetcode hot100【LeetCode 279. 完全平方数】java实现
        OpenWrt下安装Mosquitto
        AnatoMask论文汇总
        【AI日记】24.11.01 LangChain、openai api和github copilot
      • 热门文章
      • 十款代码表白小特效 一个比一个浪漫 赶紧收藏起来吧!!!
        奉劝各位学弟学妹们,该打造你的技术影响力了!
        五年了,我在 CSDN 的两个一百万。
        Java俄罗斯方块,老程序员花了一个周末,连接中学年代!
        面试官都震惊,你这网络基础可以啊!
        你真的会用百度吗?我不信 — 那些不为人知的搜索引擎语法
        心情不好的时候,用 Python 画棵樱花树送给自己吧
        通宵一晚做出来的一款类似CS的第一人称射击游戏Demo!原来做游戏也不是很难,连憨憨学妹都学会了!
        13 万字 C 语言从入门到精通保姆级教程2021 年版
        10行代码集2000张美女图,Python爬虫120例,再上征途
      Copyright © 2022 侵权请联系2656653265@qq.com    京ICP备2022015340号-1
      正则表达式工具 cron表达式工具 密码生成工具

      京公网安备 11010502049817号