码农知识堂 - 1000bd
  •   Python
  •   PHP
  •   JS/TS
  •   JAVA
  •   C/C++
  •   C#
  •   GO
  •   Kotlin
  •   Swift
  • Java泛型,这个范可真行


    🏀 一、泛型的概念

    🏄①专业理解:所谓泛型,就是允许在定义类、接口时通过一个标识表示类中某个属性的类型或者是某个方法的返回值及参数类型。 这个类型参数将在使用时(例如,继承或实现这个接口, 用这个类型声明变量、 创建对象时) 确定(即传入实际的类型参数, 也称为类型实参) 。

    🏄②通俗理解:泛型就是标签!举例:超市中的商品;药店中药盒子上贴的标识。

    🏀 二、为何要有泛型

    ⛳️①解决元素存储的安全性问题。比如商品、药品标签,不会弄错。

    ⛳️②解决获取数据元素时,需要类型强制转换的问题。比如不用每回拿商品、药品都要辨别。

    ⛳️③Java泛型可以保证如果程序在编译时没有发出警告,运行时就不会产生ClassCastException异常。同时,在代码层面上说显得更加简洁、健壮。

    🏀 三、集合中使用泛型

    🏂①集合接口或集合类在jdk5.0时都修改为带泛型的结构

    🏂②在实例化集合类时,可以指明具体的泛型类型

    🏂③指明完成以后,在集合类或接口中凡是定义类或接口时,内部结构使用到类的泛型的位置,都指定为实例化的泛型类型

    🏂④注意点:泛型的类型必须是类,不能是基本数据类型。需要用到基本数据类型的位置,需要我们拿包装类来进行替换

    🏂⑤如果实例化时,没有指明泛型的类型,默认类型为java.lang.Object类型

    🎯如下为集合中使用泛型的实例代码演示:

    package com.java.generic;
    
    import com.java.collection.Person;
    import org.junit.Test;
    
    import java.util.*;
    
    /**
     * @ClassName: GenericTest
     * @Description:
     * @Author: YuHao
     * @Date: 2022/3/2
     */
    public class GenericTest {
        //在集合中使用泛型的情况:以HashMap为实例
        @Test
        public void test3(){
            //jdk7的新特性:类型推断
            Map<String,Integer> map = new HashMap<>();
    //        Map map = new HashMap();
            map.put("Tom",56);
            map.put("Jerry",86);
            map.put("Curry",66);
    
    //        map.put(56,123);
            //泛型的嵌套
            Set<Map.Entry<String,Integer>> entry = map.entrySet();
            Iterator<Map.Entry<String, Integer>> iterator = entry.iterator();
            while (iterator.hasNext()){
                Map.Entry<String, Integer> entry1 = iterator.next();
                String key = entry1.getKey();
                Integer value = entry1.getValue();
                System.out.println(key+"---->"+value);
            }
        }
    
        //在集合中使用泛型的情况:以ArrayList为实例
        @Test
        public void test2(){
            ArrayList<Integer> list = new ArrayList<Integer>();
    
            list.add(78);
            list.add(7);
            list.add(8);
            list.add(178);
    
            //编译时,就会进行类型检查,保证数据的安全
    //        list.add("Tom");
            //方式一
            for(Integer score : list){
                //避免了强转操作
                int stuScore = score;
                System.out.println(stuScore);
            }
    
            //方式二
            Iterator<Integer> iterator = list.iterator();
            while (iterator.hasNext()){
                int stuScore = iterator.next();
                System.out.println(stuScore);
            }
    
        }
    
        //在集合中使用泛型之前的情况:
        @Test
        public void test1(){
            ArrayList list = new ArrayList();
    
            //需求:存放各个分数
            list.add(78);
            list.add(7);
            list.add(8);
            list.add(178);
    
            //问题一:类型不安全
            list.add("Tom");
    
            for(Object score : list){
                //问题二:强转时,有可能出现类型转换异常ClassCastException
                int stuScore = (Integer) score;
                System.out.println(stuScore);
            }
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86

    🏀 四、自定义泛型结构

    🎾(1)泛型类、泛型接口

    🎨①泛型类及泛型接口的的声明
    例:interface List 和 Class Demo
    其中,T,K,V并不代表值,而是表示类型。这里使用任意字母皆可。常用字母T表示,为Type的缩写。

    🎨②泛型类及泛型接口的实例化
    例:List list = new ArrayList<>( ); Iterator iterator = person.iterator( );
    将集合中的内容限制为一个特定的数据类型,即是泛型的核心思想

    🎯以下为自定义泛型类的实例代码演示:

    package com.java.generic;
    
    import org.junit.Test;
    
    import java.util.ArrayList;
    import java.util.List;
    
    /**
     * @ClassName: GenericTest1
     * @Description:
     * @Author: YuHao
     * @Date: 2022/3/2
     */
    public class GenericTest1 {
    
        @Test
        public void test1(){
            //如果定义泛型类,实例化没有指明类的泛型,则认为此泛型类型为Object类型
            //要求:如果定义了类是带泛型的,建议在实例化时要指明类的泛型。
            Order order = new Order();
            order.setOrderT(123);
            order.setOrderT("ABC");
    
            //建议:实例化时指明类的泛型
            Order<String> order1 = new Order<String>("orderAA",1001,"order::aa");
            order1.setOrderT("order:bb");
            System.out.println(order1);
        }
    
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    package com.java.generic;
    
    import java.util.ArrayList;
    import java.util.List;
    
    /**
     * @ClassName: Order
     * @Description: 自定义的泛型类
     * @Author: YuHao
     * @Date: 2022/3/2
     */
    public class Order<T> {
        String orderName;
        int orderId;
        //类的内部结构就可以使用类的泛型
        T orderT; //T其实并不是一个类,实际上就是一个参数而已
    
        public Order(){
    
        }
    
        public Order(String orderName, int orderId, T orderT){
            this.orderName = orderName;
            this.orderId = orderId;
            this.orderT = orderT;
        }
    
        public T getOrderT(){
            return orderT;
        }
    
        public void setOrderT(T orderT){
            this.orderT = orderT;
        }
    
        @Override
        public String toString() {
            return "Order{" +
                    "orderName='" + orderName + '\'' +
                    ", orderId=" + orderId +
                    ", orderT=" + orderT +
                    '}';
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45

    🎾(2)泛型方法

    🎧①泛型方法的格式:
    [访问权限] <泛型> 返回类型 方法名([泛型标识 参数名称]) 抛出的异常

    🎧②注意项:

    泛型方法:在方法中出现了泛型的结构,泛型参数与类的泛型参数没有任何关系,换句话说:泛型方法所属的类是不是泛型类都没有关系
    泛型方法:可以声明为静态的。原因:泛型参数是在调用方法时确定的,并非在实例化类时确定。
    
    • 1
    • 2

    🎯以下为自定义泛型方法的实例代码演示:

    package com.java.generic;
    
    import org.junit.Test;
    
    import java.util.ArrayList;
    import java.util.List;
    
    /**
     * @ClassName: GenericTest1
     * @Description:
     * @Author: YuHao
     * @Date: 2022/3/2
     */
    public class GenericTest1 {
        //测试泛型方法
        @Test
        public void test4(){
            Order<String> order = new Order<>();
            Integer[] arr = new Integer[]{1,2,3,4};
            //泛型方法在调用时,指明泛型参数的类型。
            List<Integer> list = Order.copyFromArrayToList(arr);
            System.out.println(list);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    package com.java.generic;
    
    import java.util.ArrayList;
    import java.util.List;
    
    /**
     * @ClassName: Order
     * @Description: 自定义的泛型方法
     * @Author: YuHao
     * @Date: 2022/3/2
     */
    public class Order<T> {
        String orderName;
        int orderId;
        //类的内部结构就可以使用类的泛型
        T orderT; //T其实并不是一个类,实际上就是一个参数而已
    
        public Order(){
    
        }
    
        public Order(String orderName, int orderId, T orderT){
            this.orderName = orderName;
            this.orderId = orderId;
            this.orderT = orderT;
        }
    
        //如下的三个方法都不是泛型方法
        public T getOrderT(){
            return orderT;
        }
    
        public void setOrderT(T orderT){
            this.orderT = orderT;
        }
    
        @Override
        public String toString() {
            return "Order{" +
                    "orderName='" + orderName + '\'' +
                    ", orderId=" + orderId +
                    ", orderT=" + orderT +
                    '}';
        }
        
        public static <E> List<E> copyFromArrayToList(E[] arr){
            ArrayList<E> list = new ArrayList<>();
            //遍历数组,将数组元素加入到list中
            for(E e : arr){
                list.add(e);
            }
            return list;
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55

    🏀 五、泛型在继承上的体现

    🎤①类A是类B的父类,G< A >和G< B > 二者不具备子父类关系,二者是并列关系。

    🎤②补充:类A是类B的父类,A< G > B< G >

    🎯以下为泛型在继承上的实例代码演示:

    package com.java.generic;
    
    import org.junit.Test;
    
    import java.util.ArrayList;
    import java.util.List;
    
    /**
     * @ClassName: GenericTest1
     * @Description:泛型在继承上的体现
     * @Author: YuHao
     * @Date: 2022/3/2
     */
    public class GenericTest1 {
        @Test
        public void test2(){
            //由于子类在继承带泛型的父类时,指明了泛型类型。则实例化子类对象时,不再需要指明泛型。
            SubOrder sub1 = new SubOrder();
            sub1.setOrderT(123);
            System.out.println(sub1);
    
            SubOrder1<String> sub2 = new SubOrder1<>();
            sub2.setOrderT("order2....");
            System.out.println(sub2);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    package com.java.generic;
    
    /**
     * @ClassName: SubOrder
     * @Description:
     * @Author: YuHao
     * @Date: 2022/3/3
     */
    public class SubOrder extends Order<Integer>{//SubOrder不是泛型类,因为已经指明的类参数为Integer,即为普通类
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    package com.java.generic;
    
    /**
     * @ClassName: SubOrder1
     * @Description:
     * @Author: YuHao
     * @Date: 2022/3/3
     */
    public class SubOrder1<T> extends Order<T>{ //SubOrder1仍是泛型类,未指明T是什么类型的参数
    
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    🏀 六、通配符的使用

    🎼①通配符:?(就是用疑问号表示通配符),例如:List,Map,List是List< Object >等各种泛型List的父类。

    🎼②类A是类B的父类,G< A >和G< B >是没有关系的,二者共同的父类是:G< ? >

    🎼③读取:读取List的对象list中的元素时,永远是安全的,因为不管list的真实类型是什么,它包含的都是Object。

    🎼④写入:写入list中的元素时,不行。因为我们不知道c的元素类型,我们不能向其中添加对象。

    🎼⑤有限制条件的通配符:

    ? extends A :
        G 可以作为G< A > 和 G< B >的父类,其中B是A的子类(小于等于)
    ? super A :
        G 可以作为G 和 G的父类,其中B是A的父类(大于等于)
    
    • 1
    • 2
    • 3
    • 4

    🎯以下为泛型通配符使用的实例代码演示:

    package com.java.generic;
    
    import com.java.collection.Person;
    import org.junit.Test;
    
    import java.util.*;
    
    /**
     * @ClassName: GenericTest
     * @Description:
     * @Author: YuHao
     * @Date: 2022/3/2
     */
    public class GenericTest {
        /*
        有限制条件的通配符的使用
        ? extends A :
            G 可以作为G 和 G的父类,其中B是A的子类(小于等于)
    
        ? super A :
            G 可以作为G 和 G的父类,其中B是A的父类(大于等于)
         */
        @Test
        public void test7(){
    
            List<? extends Person> list1 = null;
            List<? super Person> list2 = null;
    
    
            List<Person> list4 = new ArrayList<>();
            List<Object> list5 = new ArrayList<>();
    
            //小于等于
            list1 = list4;
            //list1 = list5;
    
            //大于等于
            list2 = list4;
            list2 = list5;
    
            //读取数据:
            list1 = list4;
            list1.get(0);
            Person p = list1.get(0);
    
            //写入数据:
            list2.add(new Person());
        }
    
        @Test
        public void test6(){
            List<Object> list1 = null;
            List<String> list2 = null;
    
            List<?> list = null;
    
            list = list1;
            list = list2;
    
    //        print(list1);
    //        print(list2);
    
    
            List<String> list3 = new ArrayList<>();
            list3.add("AA");
            list3.add("BB");
            list3.add("CC");
            list = list3;
    
            //添加(写入):对于list就不能向其内部添加数据。
            //除了添加null之外,其他都不能添加
            list.add(null);
    
            //获取(读取):允许读取数据,读取的数据类型为Object。
            Object o = list.get(0);
            System.out.println(o);
        }
    
        public void print(List<?> list){
            Iterator<?> iterator = list.iterator();
            while (iterator.hasNext()){
                Object object = iterator.next();
                System.out.println(object);
            }
        }
    
        @Test
        public void test5(){
            List<String> list1 = null;
            ArrayList<String> list2 = null;
            AbstractList<String> list3 = null;
            list3 = list2;
            list1 = list2;
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96

    🍆路过的小伙伴,如果博文有帮助到你解决问题,可以点赞+收藏+关注一波呀~👊👊👊本人将会持续更新相关Java学习的博文,感谢您的支持哦!!!芜湖起飞✈️✈️✈️
    在这里插入图片描述

  • 相关阅读:
    数字图像处理之matlab常见函数
    如何通过UTON WALLET数字钱包创建和使用你的元宇宙身份
    力扣leetcode 667. 优美的排列 II
    中科院TextMind(文心)安装及使用
    show-overflow-tooltip 解决elementui el-table标签自动换行的问题
    python 源码模块打包发布
    30分钟使用百度EasyDL实现烟雾检测
    PHP包含读文件写文件
    RK3588平台开发系列讲解(SARADC篇)SARADC的工作流程
    SQL介绍
  • 原文地址:https://blog.csdn.net/qq_37530429/article/details/126369366
  • 最新文章
  • 攻防演习之三天拿下官网站群
    数据安全治理学习——前期安全规划和安全管理体系建设
    企业安全 | 企业内一次钓鱼演练准备过程
    内网渗透测试 | 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号