泛型基本说明

news2025/1/18 9:47:02
  1. 使用传统方法的问题分析
    1. 不能对加入到集合ArrayList中的数据类型进行约束(不安全)
    2. 遍历的时候,需要进行类型转换,如果集合中的数据量较大,对效率有影响。
  2. 泛型的好处
    1. 编译时,检查添加元素的类型,提高了安全性
    2. 减少了类型转换的次数,提高效率
    3. 不在提示编译警告
    4. package com.hspedu.generic.improve;
      
      import java.util.ArrayList;
      
      /**
       * @author 韩顺平
       * @version 1.0
       */
      @SuppressWarnings({"all"})
      public class Generic02 {
          public static void main(String[] args) {
      
              //使用传统的方法来解决===> 使用泛型
              //老韩解读
              //1. 当我们 ArrayList<Dog> 表示存放到 ArrayList 集合中的元素是Dog类型 (细节后面说...)
              //2. 如果编译器发现添加的类型,不满足要求,就会报错
              //3. 在遍历的时候,可以直接取出 Dog 类型而不是 Object
              //4. public class ArrayList<E> {} E称为泛型,那么 Dog->E
              ArrayList<Dog> arrayList = new ArrayList<Dog>();
              arrayList.add(new Dog("旺财", 10));
              arrayList.add(new Dog("发财", 1));
              arrayList.add(new Dog("小黄", 5));
              //假如我们的程序员,不小心,添加了一只猫
              //arrayList.add(new Cat("招财猫", 8));
              System.out.println("===使用泛型====");
              for (Dog dog : arrayList) {
                  System.out.println(dog.getName() + "-" + dog.getAge());
              }
      
      
          }
      }
      
      /*
      1.请编写程序,在ArrayList 中,添加3个Dog对象
      2.Dog对象含有name 和 age, 并输出name 和 age (要求使用getXxx())
      3.老师使用泛型来完成代码
       */
      class Dog {
          private String name;
          private int age;
          public Dog(String name, int age) {
              this.name = name;
              this.age = age;
          }
      
          public String getName() {
              return name;
          }
      
          public void setName(String name) {
              this.name = name;
          }
      
          public int getAge() {
              return age;
          }
      
          public void setAge(int age) {
              this.age = age;
          }
      }
      
      class Cat { //Cat类
          private String name;
          private int age;
          public Cat(String name, int age) {
              this.name = name;
              this.age = age;
          }
      
          public String getName() {
              return name;
          }
      
          public void setName(String name) {
              this.name = name;
          }
      
          public int getAge() {
              return age;
          }
      
          public void setAge(int age) {
              this.age = age;
          }
      }
      
  3. 泛型说明

    1. package com.hspedu.generic;
      
      import java.util.List;
      
      /**
       * @author 韩顺平
       * @version 1.0
       */
      public class Generic03 {
          public static void main(String[] args) {
      
              //注意,特别强调: E具体的数据类型在定义Person对象的时候指定,即在编译期间,就确定E是什么类型
              Person<String> person = new Person<String>("韩顺平教育");
              person.show(); //String
      
              /*
                  你可以这样理解,上面的Person类
                  class Person {
                      String s ;//E表示 s的数据类型, 该数据类型在定义Person对象的时候指定,即在编译期间,就确定E是什么类型
      
                      public Person(String s) {//E也可以是参数类型
                          this.s = s;
                      }
      
                      public String f() {//返回类型使用E
                          return s;
                      }
                  }
               */
      
              Person<Integer> person2 = new Person<Integer>(100);
              person2.show();//Integer
      
              /*
                  class Person {
                      Integer s ;//E表示 s的数据类型, 该数据类型在定义Person对象的时候指定,即在编译期间,就确定E是什么类型
      
                      public Person(Integer s) {//E也可以是参数类型
                          this.s = s;
                      }
      
                      public Integer f() {//返回类型使用E
                          return s;
                      }
                  }
               */
          }
      }
      
      //泛型的作用是:可以在类声明时通过一个标识表示类中某个属性的类型,
      // 或者是某个方法的返回值的类型,或者是参数类型
      
      class Person<E> {
          E s ;//E表示 s的数据类型, 该数据类型在定义Person对象的时候指定,即在编译期间,就确定E是什么类型
      
          public Person(E s) {//E也可以是参数类型
              this.s = s;
          }
      
          public E f() {//返回类型使用E
              return s;
          }
      
          public void show() {
              System.out.println(s.getClass());//显示s的运行类型
          }
      }
      

      E就代表你这个集合里的元素是什么类型的元素,而且必须是引用类型,不能是基本数据类型

    2. 泛型又称参数化类型,是JDK5.0出现的新特性,解决数据类型的安全性问题

    3. 在类声明或实例化时只要指定好需要的具体的类型即可

    4. 泛型的作用:可以在类声明时通过一个标识表示类中某个属性的类型,或者是某个方法的返回值的类型,或者是参数类型

  4. 泛型的语法

    1. interface 接口<E>{}和class 类<K,V>{}

    2. 字母不代表值,而是数据类型

  5. 应用实例

    1. package com.jshedu.generic;
      
      import java.util.*;
      
      /**
       * @author Mr.jia
       * @version 1.0
       * 创建  3个学生对象
       * 放到HashSet中学生对象,要求Key是String name,Value就是学生对象
       */
      
      public class Generic02 {
          public static void main(String[] args) {
              HashSet<Student> students = new HashSet<Student>();
              students.add(new Student("jack",28));
              students.add(new Student("tom",23));
              students.add(new Student("lucy",26));
              //遍历
              for (Student o :students) {
                  System.out.println(o);
              }
              //使用泛型方式给HashMap放入3个学生,这个是两个参数的,
              //HashMap<String, Student>,传参时也要两个
              HashMap<String, Student> ssh = new HashMap<String, Student>();
              //迭代器里面的参数为什么会自动填充String,Student
              //定义HashMap的时候已经把k和V指定了
              ssh.put("tom",new Student("tom",58));
              ssh.put("king",new Student("king",48));
              ssh.put("rose",new Student("rose",38));
              //迭代器EntrySet
              Set<Map.Entry<String, Student>> entries = ssh.entrySet();
              Iterator<Map.Entry<String, Student>> iterator = entries.iterator();
              while (iterator.hasNext()) {
                  Map.Entry<String, Student> next =  iterator.next();
                  System.out.println(next.getKey()+"-"+next.getValue());
              }
      
      
          }
      }
      class Student{
          private String name;
          private int age;
      
          public Student(String name, int age) {
              this.name = name;
              this.age = age;
          }
      
          public String getName() {
              return name;
          }
      
          public void setName(String name) {
              this.name = name;
          }
      
          public int getAge() {
              return age;
          }
      
          public void setAge(int age) {
              this.age = age;
          }
      
          @Override
          public String toString() {
              return "Student{" +
                      "name='" + name + '\'' +
                      ", age=" + age +
                      '}';
          }
      }
      

      注意自动填充是从HashMap的K和V来的

  6. 泛型注意事项

    1. E不能为基本数据类型,要求为引用类型

    2. 在给泛型指定具体类型后,可以传入该类型或者其子类类型

    3. 如果这样写泛型默认是Object 。ArrayList arrayList = new ArrayList();

    4. 等价ArrayList<Object> objects = new ArrayList<>();

  7. package com.jshedu.generic;
    
    import java.util.ArrayList;
    import java.util.Comparator;
    
    /**
     * @author Mr.jia
     * @version 1.0
     */
    
    public class Homework01 {
        public static void main(String[] args) {
            ArrayList<Employee> employees = new ArrayList<>();
            employees.add(new Employee("jack",12222,new MyDate(2023,4,17)));
            employees.add(new Employee("tomwaew",10000,new MyDate(2023,5,17)));
            employees.add(new Employee("tomwewewe",22222,new MyDate(2023,6,17)));
            
            System.out.println(employees);
    
            employees.sort(new Comparator<Employee>() {
                @Override
                public int compare(Employee o1, Employee o2) {
                    //先按照name排序,如果name相同,则按照生日日期
                    //先对传入的参数进行验证
                    if(!(o1 instanceof Employee && o2 instanceof Employee)){
                        System.out.println("类型不正确...");
                        return 0;
                    }
                    //比较name,这里是o1对象调用compareTo方法
                    //name是比较的字母谁在前,不是name的长度
                    int i = o1.getName().compareTo(o2.getName());
                    if(i !=0){
                        return i;
                    }
                    //如果name相同,就比较birthday-year
                    int yearMinus = o1.getBirthday().getYear()-o2.getBirthday().getYear();
                    if(yearMinus != 0){
                        return yearMinus;
                    }
                    //如果year相同,就比较month
                    int monthMinus = o1.getBirthday().getMonth()-o2.getBirthday().getMonth();
                    if(monthMinus != 0){
                        return monthMinus;
                    }
    
                    //year和month都相同
                    return o1.getBirthday().getDay()-o2.getBirthday().getDay();
    
                }
            });
            System.out.println("排序后=========");
            System.out.println(employees);
    
    
        }
    
    }
    class Employee{
        private String name;
        private double sal;
        private MyDate birthday;
    
        public Employee(String name, double sal, MyDate birthday) {
            this.name = name;
            this.sal = sal;
            this.birthday = birthday;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public double getSal() {
            return sal;
        }
    
        public void setSal(double sal) {
            this.sal = sal;
        }
    
        public MyDate getBirthday() {
            return birthday;
        }
    
        public void setBirthday(MyDate birthday) {
            this.birthday = birthday;
        }
    
        @Override
        public String toString() {
            return "\nEmployee{" +
                    "name='" + name + '\'' +
                    ", sal=" + sal +
                    ", birthday=" + birthday +
                    '}';
        }
    }
    class MyDate{
        private int month;
        private int day;
        private int year;
    
        public MyDate(int year, int month, int day) {
            this.month = month;
            this.day = day;
            this.year = year;
        }
    
        public int getMonth() {
            return month;
        }
    
        public void setMonth(int month) {
            this.month = month;
        }
    
        public int getDay() {
            return day;
        }
    
        public void setDay(int day) {
            this.day = day;
        }
    
        public int getYear() {
            return year;
        }
    
        public void setYear(int year) {
            this.year = year;
        }
    
        @Override
        public String toString() {
            return "MyDate{" +
                    "month=" + month +
                    ", day=" + day +
                    ", year=" + year +
                    '}';
        }
    }
    

    Arrays.sort()底层代码,可以把年月日的比较封装到MyDate,MyDate接口实现Comparable<MyDate>,然后重写Comparable接口下的compareTo(MyDate o)方法

  8.  

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/428115.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

springbean 的 setter/构造注入

文章目录前言一、另外两种注入的怎么用&#xff1f;二、使用setter和构造注入的步骤1. 搞一个配置类,用户获取spring容器中的bean2. 由于有静态方法,所以直接调用三、使用final 的构造注入方式(推荐)总结前言 我们知道,一般java中的依赖注入有三种: 1 属性注入 2 settter注入 …

Golang每日一练(leetDay0039) 二叉树专题(8)

目录 115. 不同的子序列 Distinct Subsequences &#x1f31f;&#x1f31f;&#x1f31f; 116. 填充每个节点的下一个右侧节点指针 Populating-next-right-pointers-in-each-node &#x1f31f;&#x1f31f; 117. 填充每个节点的下一个右侧节点指针 II Populating-next-ri…

模拟信号放大转换器 非隔离 线性对应输入输出 大功率负载

概述&#xff1a; 导轨安装DIN11 NIPO 系列模拟信号放大器是一种将输入信号放大、转换成按比例输出的直流信号放大器。产品广泛应用在电力、远程监控、仪器仪表、医疗设备、工业自控等需要直流信号测控的行业。此系列产品内部采用稳压电路&#xff0c;通过等比例控制线性放大输…

Threshold ECDSA——web3.0开发中的门限签名

多重签名 1.联名账户&#xff0c;任何一个密钥都能打开账户。 2.储蓄账户&#xff0c;需要所有密钥才能打开账户。 3.级联账户&#xff0c;可以使用部分密钥做部分功能&#xff0c;需要所有密钥才能执行全部功能。 4.在加密货币中&#xff0c;多重签名通过创建一个多重签名…

超详细从入门到精通,pytest自动化测试框架实战-fixture多样玩法(九)

目录&#xff1a;导读前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09;前言 在编写测试用例&…

uniapp开发小程序:使用webview 跳转外部链接

一、使用uniapp开发小程序时&#xff0c;要跳转外部链接&#xff0c;实现的效果如下&#xff1a; 二、实现的步骤&#xff1a; ①先在自己uniapp项目pages.json中建一个页面webview.vue {"path" : "pages/webview/webview","style" : …

(详细)带你运行ShanghaiTech数据集预训练模型——人群计数算法

写在前面 ShanghaiTech数据集是现有的人群计数领域比较常用的训练测试数据集&#xff0c;该博客将详细讲述如何跑通ShanghaiTech官方提供的预训练版本。 由于全部跑完ShanghaiTech数据集需要一定的时间&#xff0c;今天只以其中的ped2数据集&#xff08;体量最小&#xff09;…

linux_回收子进程(何为孤儿进程、僵尸进程、wait函数、waitpid函数)

接上一篇&#xff1a;linux_exec函数族-execl函数-execlp函数-execle函数-execv函数-execvp函数-execve函数 今天来向大家分享几个有趣的知识点&#xff0c;一个是孤儿进程&#xff0c;一个是僵尸进程&#xff0c;hhh&#xff0c;是不是很有趣&#xff0c;另外再来看看怎么去回…

Kubernetes集群调度增强之超容量扩容

作者&#xff1a;京东科技 徐宪章 1 什么是超容量扩容 超容量扩容功能&#xff0c;是指预先调度一定数量的工作节点&#xff0c;当业务高峰期或者集群整体负载较高时&#xff0c;可以使应用不必等待集群工作节点扩容&#xff0c;从而迅速完成应用横向扩容。通常情况下HPA、Cl…

链表与邻接表|栈与队列|kmp

目录 单链表&#xff08;邻接表&#xff09; 双链表 数组模拟栈、队列 单调栈 单调队列&#xff08;滑动窗口&#xff09; KMP 一、KMP算法基本概念与核心思想 二、next数组的含义 三、匹配的思路 四、求next数组 单链表&#xff08;邻接表&#xff09; #include &…

Linux操作基础(系统安全及应用)

文章目录一 、账号安全基本措施1.1 系统账号清理1.2 密码安全控制1.21 设置密码有效期1.3 命令历史限制1.31 修改history命令条数1.32 清空history的方式1.33 设置终端自动注销二 、使用su命令切换用户2.1 限制使用su命令切换用户2.2 sudo命令—提升执行权限三 、系统引导和登录…

OpenCV:介绍 SURF(加速稳健特征)以及其使用

我们将了解 SURF 的基础知识 我们将了解 OpenCV 中的 SURF 功能 理论 在上一章中,我们学习了 SIFT 用于关键点检测和描述的方法。但它相对较慢,人们需要更快速的版本。2006年,Bay, H., Tuytelaars, T. 和 Van Gool, L 发表了另一篇论文 "SURF: 加速稳健特征",介…

机器学习:多项式拟合分析中国温度变化与温室气体排放量的时序数据

文章目录1、前言2、定义及公式3、案例代码1、数据解析2、绘制散点图3、多项式回归、拟合4、注意事项1、前言 ​ 当分析数据时&#xff0c;如果我们找的不是直线或者超平面&#xff0c;而是一条曲线&#xff0c;那么就可以用多项式回归来分析和预测。 2、定义及公式 ​ 多项式…

《花雕学AI》哪种技能5年10年后还会被市场需要? 该如何提高这些能力?

随着AI人工智能、ChatGPT等新的技术革新的发展&#xff0c;未来职业场景确实会发生变化&#xff0c;一些传统的职业可能会被取代&#xff0c;而一些新的职业可能会出现。根据世界经济论坛所发布的《未来就业报告》&#xff0c;一半的劳动力需要在2025年之前完成技能重塑。那么&…

Harmony OS 开发指南——DevEco Device Tool 安装配置

本文介绍如何在Windows主机上安装DevEco Device Tool工具。 坑点总结&#xff1a; 国内部分网络环境下&#xff0c;安装npm包可能会很慢或者超时&#xff0c;推荐使用国内npm源&#xff08;如淘宝源、华为源等&#xff09;&#xff1b;serialport这个npm包安装的过程中需要编…

C/C++笔记-记录一次对qmake生成的Makefile的分析(2023-02-07)

如下Qt代码&#xff1a; ConsoleDemo.pro QT core QT - guiTARGET ConsoleDemo CONFIG console CONFIG - app_bundleTEMPLATE appSOURCES main.cpp main.cpp #include <QCoreApplication> #include <QDebug>int main(int argc, char *argv[]) {QCoreApplic…

安装Kafka 基础命令

目录 解压 改名 修改配置文件 创建目录用于存放日志 创建修改myid 添加环境变量 刷新环境变量 测试 启动zookeeper 启动kafka 关闭kafka kafka基础命令 查看消息队列 创建消息队列 查看队列详情 查询指定队列消息数量 生产者消费者 生产消息 消费消息 解压 …

简单分享婚庆小程序开发怎么做

婚庆行业的服务范围不再仅限于婚纱照、婚礼主持等服务&#xff0c;消费者希望在婚庆服务商获得更多的服务&#xff0c;导致行业服务范围不断扩大、服务类目越发丰富&#xff0c;而商家在此基础上&#xff0c;更需要考虑提高服务质量与效率&#xff0c;合理利用资源提供服务。小…

Jmeter5.1的安装

1.由于&#xff0c;jmeter 是用纯java开发的一个可跨平台的绿色软件&#xff0c;所以&#xff0c;我们在使用jmeter之前&#xff0c;必须要安装基于Windows下的jdk环境。下面安装jdk,检查是否安装jdk方法&#xff08;cmd运行输入java -version&#xff09;&#xff0c;如下图显…

81.qt qml-Canvas深入学习之好看的水纹波自定义控件V2

界面如下所示(外观参考ECharts 源码通过QML控件实现): 效果如下所示: 支持自定义颜色、自定义波峰数量、增幅、速度、水平偏移等 1.介绍 在我们之前38章38.qt quick-QML水纹波进度条_诺谦的博客-CSDN博客 写过一个简单的水纹波: 所以本质差不多. 2.QianRippleChartPage代码 该…