当前位置: 首页 > news >正文

泛型的详解

泛型的理解和好处

首先我们先来看看泛型的好处

1)编译时,检查添加元素的类型,提高了安全性

2)减少了类型转换的次数,提高效率[说明]

不使用泛型 Dog -> Object -> Dog//放入到ArrayList 会先转成Object,在取出时,还需要转换成Dog使用泛型 Dog-> Dog -> Dog//放入时,和取出时,不需要类型转换,提高效率

3)不再提示编译警告

代码演示:

注意:
1.当我们在集合的后面指定了泛型,那么表示存放到集合中的元素的类型是dog类型

2.如果我们加入的类型不是dog那么编译器会直接报错

3.我们在遍历的时候,可以直接取出dog的类型而不是Object

package idea.chapter15.generic.improve;import java.util.ArrayList;@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->EArrayList<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;}
}

 

泛型的介绍

理解:泛(广泛)型(类型)=> Integer,String,Dog 

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

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

3)Java泛型可以保证如果程序在编译时没有发出警告,运行时就不会产ClassCastException异常。同时,代码更加简洁、健壮

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

代码演示:

注意:

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

class Person <E> 红色标注的这一块就是泛型,在代码中我们可以看到,我们在类的后面加入了<E>就表示该一个类型,后面根据我们传入的不同的对象,比如我们传入的是一个String,那么E就是String类型的,传入的是一个Integer 那么E 就是一个Integer

package idea.chapter15.generic;public class Generic03 {public static void main(String[] args) {//注意,特别强调: E具体的数据类型在定义Person对象的时候指定,即在编译期间,就确定E是什么类型Person<String> person = new Person<String>("jack");person.show(); //String/*你可以这样理解,上面的Person类class Person {String s ;//E表示 s的数据类型, 该数据类型在定义Person对象的时候指定,即在编译期间,就确定E是什么类型public Person(String s) {//E也可以是参数类型this.s = s;}public String f() {//返回类型使用Ereturn 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() {//返回类型使用Ereturn s;}}*/}
}//泛型的作用是:可以在类声明时通过一个标识表示类中某个属性的类型,
// 或者是某个方法的返回值的类型,或者是参数类型class Person<E> {E s ;//E表示 s的数据类型, 该数据类型在定义Person对象的时候指定,即在编译期间,就确定E是什么类型public Person(E s) {//E也可以是参数类型this.s = s;}public E f() {//返回类型使用Ereturn s;}public void show() {System.out.println(s.getClass());//显示s的运行类型}
}

泛型的语法

泛型的声明

interface接口<T>和class 类<K,V>

//比如:List,ArrayList

说明: 1)其中,T,K,V不代表值,而是表示类型。

2)任意字母都可以。常用T表示,是Type的缩写

泛型的实例化:

要在类名后面指定类型参数的值(类型)

  1. List<String> strList =new ArrayList<String>(); [举例说明]

  2. Iterator<Customer> iterator = customers.iterator();

泛型课堂练习

代码演示:

package idea.chapter15.generic;import java.util.*;/*
练习:
1. 创建3个学生对象
2. 放入到HashMap中,要求Key是String name,Value就是 学生对象
3.使用两种方式遍历*/
@SuppressWarnings({"all"})
public class GenericExercise {public static void main(String[] args) {HashSet<Student> students = new HashSet<>();students.add(new Student("jack", 12));students.add(new Student("tom", 10));students.add(new Student("smith", 1));//        //使用增强for遍历
//        System.out.println("使用增强for的方式");
//        for (Student student : students) {
//            System.out.println(student);
//        }
//
//        //使用迭代器
//        System.out.println("使用迭代器的方式");
//        Iterator<Student> iterator = students.iterator();
//        while (iterator.hasNext()) {
//            Student next = iterator.next();
//            System.out.println(next);
//        }//使用HashMapHashMap<String, Student> hashMap = new HashMap<>();hashMap.put("jack", new Student("jack", 1));hashMap.put("tom", new Student("tom", 11));hashMap.put("mary", new Student("mary", 111));//使用增强forSet<String> strings = hashMap.keySet();for (String string : strings) {System.out.println(string + "-" + hashMap.get(string));}//使用迭代器System.out.println("\n使用迭代器的方式");Set<Map.Entry<String, Student>> entries = hashMap.entrySet();Iterator<Map.Entry<String, Student>> iterator = entries.iterator();while (iterator.hasNext()) {//此时的next就是一个EntryMap.Entry<String, Student> next = iterator.next();System.out.println(next.getKey() + "-" + next.getValue());}}
}class Student {private String name;private int id;public Student(String name, int id) {this.name = name;this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getId() {return id;}public void setId(int id) {this.id = id;}@Overridepublic String toString() {return "Student{" +"name='" + name + '\'' +", id=" + id +'}';}
}

泛型使用的注意事项和细节

1.interface List<T>0,public class HashSet<E>{}..等等,说明:T,E只能是引用类型

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

3.泛型使用形式

List<Integer> list1=new ArrayList<Integer>{};
List<Integer>list2=new ArrayList<>);

3.如果我们这样写 List list3=new ArrayList0;默认给它的 泛型是[<E> E就是Object]即:

代码演示:

package idea.chapter15.generic;import java.util.ArrayList;
import java.util.List;/*** 讲解泛型的注意事项和使用细节*/
@SuppressWarnings({"all"})
public class GenericDetail {public static void main(String[] args) {//1.给泛型指向数据类型是,要求是引用类型,不能是基本数据类型List<Integer> list = new ArrayList<Integer>(); //OK//List<int> list2 = new ArrayList<int>();//错误//2. 说明//因为 E 指定了 A 类型, 构造器传入了 new A()//在给泛型指定具体类型后,可以传入该类型或者其子类类型Pig<A> aPig = new Pig<A>(new A());aPig.f();Pig<A> aPig2 = new Pig<A>(new B());aPig2.f();//3. 泛型的使用形式ArrayList<Integer> list1 = new ArrayList<Integer>();List<Integer> list2 = new ArrayList<Integer>();//在实际开发中,我们往往简写//编译器会进行类型推断, 老师推荐使用下面写法ArrayList<Integer> list3 = new ArrayList<>();List<Integer> list4 = new ArrayList<>();ArrayList<Pig> pigs = new ArrayList<>();//4. 如果是这样写 泛型默认是 ObjectArrayList arrayList = new ArrayList();//等价 ArrayList<Object> arrayList = new ArrayList<Object>();/*public boolean add(Object e) {ensureCapacityInternal(size + 1);  // Increments modCount!!elementData[size++] = e;return true;}*/Tiger tiger = new Tiger();//如果什么都不写,默认是Object,也就是下面的这种方式/*class Tiger {//类Object e;public Tiger() {}public Tiger(Object e) {this.e = e;}}*/}
}class Tiger<E> {//类E e;public Tiger() {}public Tiger(E e) {this.e = e;}
}class A {
}class B extends A {
}class Pig<E> {//E e;public Pig(E e) {this.e = e;}public void f() {System.out.println(e.getClass()); //运行类型}
}

泛型练习2

代码演示:

package idea.chapter15.generic;import java.util.ArrayList;
import java.util.Comparator;/*
泛型课堂练习题
定义Employee类
1)该类包含:private成员变量name,sal,birthday,其中birthday为MyDate类的对象;
2)为每一个属性定义getter,setter方法;
3)重写 toString 方法输出 name,sal,birthday
4) MyDate类包含:private成员变量month,day.year;并为每一个属性定义getter setter 方法;
5)创建该类的3个对象,并把这些对象放入ArrayList集合中(ArrayList需使用泛型来定义),对集合中的元素进行排序,并遍历输出:
排序方式:调用ArrayList的sort 方法,传入 Comparator对象[使用泛型],先按照name排序,如果name相同,则按生日日期的先后排序。 【即:定制排序】
有一定难度15min,比较经典 泛型使用案例*/
@SuppressWarnings({"all"})
public class GenericExercise02 {public static void main(String[] args) {ArrayList<Employee> employees = new ArrayList<>();employees.add(new Employee("jack", 200, new MyDate(2001, 1, 1)));employees.add(new Employee("tom", 100, new MyDate(2003, 3, 2)));employees.add(new Employee("tom", 300, new MyDate(2002, 5, 3)));employees.sort(new Comparator<Employee>() {@Overridepublic int compare(Employee o1, Employee o2) {//根据要求,如果名字相同我们按照出生日期比较,如果名字不相同就按照名字比较if (o1.getName().equals(o2.getName())) {return o1.getBirthday().getYear() - o2.getBirthday().getYear();} else//还可以继续增加逻辑,比如出生年份相同就按照月份比较return o1.getName().equals(o2.getName()) ? 1 : -1;}});System.out.println(employees);}
}class Employee implements Comparator {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;}@Overridepublic String toString() {return "\nEmployee{" +"name='" + name + '\'' +", sal=" + sal +", birthday=" + birthday +'}';}@Overridepublic int compare(Object o1, Object o2) {return 0;}
}class MyDate {private int year;private int month;private int day;public MyDate(int year, int month, int day) {this.year = year;this.month = month;this.day = day;}public int getYear() {return year;}public void setYear(int year) {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;}@Overridepublic String toString() {return "MyDate{" +"year=" + year +", month=" + month +", day=" + day +'}';}
}

相关文章:

泛型的详解

泛型的理解和好处 首先我们先来看看泛型的好处 1)编译时&#xff0c;检查添加元素的类型&#xff0c;提高了安全性 2)减少了类型转换的次数&#xff0c;提高效率[说明] 不使用泛型 Dog -> Object -> Dog//放入到ArrayList 会先转成Object&#xff0c;在取出时&#x…...

用科技创造未来!流辰信息技术助您实现高效办公

随着社会的迅猛发展&#xff0c;科技的力量无处不见。它正在悄悄地改变整个社会&#xff0c;让人类变得进步和文明&#xff0c;让生活变得便捷和高效。在办公自动化强劲发展的今天&#xff0c;流辰信息技术让通信业、电网、汽车、物流等领域的企业实现了高效办公&#xff0c;数…...

基于R语言APSIM模型

随着数字农业和智慧农业的发展&#xff0c;基于过程的农业生产系统模型在模拟作物对气候变化的响应与适应、农田管理优化、作物品种和株型筛选、农田固碳和温室气体排放等领域扮演着越来越重要的作用。 APSIM (Agricultural Production Systems sIMulator)模型是世界知名的作物…...

块状链表实现BigString大字符串操作(golang)

前言 块状链表是介于链表和数组之间的数据结构&#xff0c;能够在 O ( n ) O(\sqrt{n}) O(n ​)时间内完成插入、删除、访问操作。 数据结构如图所示。假设最大容量为 n n n, 则它有一个长度为 s n s\sqrt{n} sn ​的链表。链表中每个结点是一个长度为 2 n 2 \times \sqrt{…...

项目问题记录(持续更新)

1.在 yarn install的时候报 error achrinza/node-ipc9.2.2: The engine "node" is incompatible with this module. Expected version "8 || 10 || 12 || 14 || 16 || 17". Got "20.1.0" error Found incompatible module.需要执行 yarn config…...

Linux的进程

目录 一、进程占用的内存资源 二、进程的系统环境 三、进程一直在切换 四、父进程和子进程 五、进程状态 六、查看进程 1.ps -ef 列出所有进程 2.ps -lax 列出所有进程 3.ps aux列出所有进程 4.树形列出所有进程 七、作业&#xff08;用来查看管理进程&#xff09; …...

与其焦虑被 AI 取代或猜测前端是否已死, 不如看看 vertical-align 扎实你的基础!!!

与其焦虑被 AI 取代或猜测前端是否已死, 不如看看 vertical-align 扎实你的基础!!! vertical-align 设置 display 值为 inline, inline-block 和 table-cell 的元素竖直对齐方式. 从 line-height: normal 究竟是多高说起 我们先来看一段代码, 分析一下为什么第二行的行高, 也就…...

路由、交换机、集线器、DNS服务器、广域网/局域网、端口、MTU

前言&#xff1a;网络名词术语解析(自行阅读扫盲)&#xff0c;推荐大家去读户根勤的《网络是怎样连接的》 路由(route)&#xff1a; 数据包从源地址到目的地址所经过的路径&#xff0c;由一系列路由节点组成。某个路由节点为数据包选择投递方向的选路过程。 路由器工作原理 路…...

在全志V851S开发板上进行屏幕触摸适配

1.修改屏幕驱动 从ft6236 &#xff08;删掉&#xff0c;不要保留&#xff09;&#xff0c;改为下面的 路径&#xff1a;/home/wells/tina-v853-open/tina-v853-open/device/config/chips/v851s/configs/lizard/board.dts&#xff08;注意路径&#xff0c;要设置为自己的实际路…...

字符串拷贝时的内存重叠问题

字符串拷贝时的内存重叠问题 1.什么是内存重叠 拷贝的目的地址在源地址的范围内&#xff0c;有重叠。 如在写程序的过程中&#xff0c;我们用到的strcpy这个拷贝函数&#xff0c;在这个函数中我们定义一个目的地址&#xff0c;一个源地址&#xff0c;在拷贝的过程中如果内存重…...

告别PPT手残党!这6款AI神器,让你秒变PPT王者!

如果你是一个PPT手残党&#xff0c;每每制作PPT总是让你焦头烂额&#xff0c;那么你一定需要这篇幽默拉风的推广文案&#xff01; 我向你保证&#xff0c;这篇文案将帮助你发现6款AI自动生成PPT的神器&#xff0c;让你告别PPT手残党的身份&#xff0c;成为一名PPT王者。 无论…...

JVM配置与优化

参考&#xff1a; JVM内存分区及作用&#xff08;JDK8&#xff09; https://blog.csdn.net/BigBug_500/article/details/104734957 java 进程占用系统内存过高分析 https://blog.csdn.net/fxh13579/article/details/104754340 Java之jvm和线程的内存 https://blog.csdn.ne…...

电力系统储能调峰、调频模型研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…...

C++基础之类、对象一(类的定义,作用域、this指针)

目录 面向对象的编程 类的引入 简介 类的定义 简介 访问限定符 命名规则 封装 简介 类的作用域 类的大小及存储模型 this指针 简介 面向对象的编程 C与C语言不同&#xff0c;C是面向对象的编程&#xff0c;那么什么是面向对象的编程呢&#xff1f; C语言编程&#xff0c;规定…...

javaScript---设计模式-封装与对象

目录 1、封装对象时的设计模式 2、基本结构与应用示例 2.1 工厂模式 2.2 建造者模式 2.3 单例模式 封装的目的&#xff1a;①定义变量不会污染外部&#xff1b;②能作为一个模块调用&#xff1b;③遵循开闭原则。 好的封装&#xff08;不可见、留接口&#xff09;&#xff1a;①…...

【消息中间件】kafka高性能设计之内存池

文章目录 前言实现创建内存池分配内存释放内存 总结 前言 Kafka的内存池是一个用于管理内存分配的缓存区域。它通过在内存上保留一块固定大小的内存池&#xff0c;用于分配消息缓存、批处理缓存等对象&#xff0c;以减少频繁调用内存分配函数的开销。 Kafka内存池的实现利用了…...

创建型模式——单例(singleton)

1. 模式说明 单例模式保证类只有一个实例&#xff1b;创建一个对象&#xff0c;当你创建第二个对象的时候&#xff0c;此时你获取到的是已经创建过的对象&#xff0c;而不是一个新的对象&#xff1b; 1.1 使用场景 共享资源的访问权限&#xff1b;任务的管理类&#xff1b;数…...

算法:迷宫问题

描述 定义一个二维数组 N*M &#xff0c;如 5 5 数组下所示&#xff1a; int maze[5][5] { 0, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, }; 它表示一个迷宫&#xff0c;其中的1表示墙壁&#xff0c;0表示可以走的路&#xff0c;只能横着走或…...

聊聊并发编程的12种业务场景

前言 并发编程是一项非常重要的技术&#xff0c;无论在面试&#xff0c;还是工作中出现的频率非常高。 并发编程说白了就是多线程编程&#xff0c;但多线程一定比单线程效率更高&#xff1f; 答&#xff1a;不一定&#xff0c;要看具体业务场景。 毕竟如果使用了多线程&…...

MySQL执行顺序

MySQL执行顺序 MySQL语句的执行顺序也是在面试过程中经常问到的问题&#xff0c;并且熟悉执行顺序也有助于SQL语句的编写。 SELECT FROM JOIN ON WHERE GROUP BY HAVING ORDER BY LIMIT执行顺序如下&#xff1a; FROM ON JOIN WHERE GROUP BY # (开始使用别名) SUM # SUM等…...

第19节 Node.js Express 框架

Express 是一个为Node.js设计的web开发框架&#xff0c;它基于nodejs平台。 Express 简介 Express是一个简洁而灵活的node.js Web应用框架, 提供了一系列强大特性帮助你创建各种Web应用&#xff0c;和丰富的HTTP工具。 使用Express可以快速地搭建一个完整功能的网站。 Expre…...

React 第五十五节 Router 中 useAsyncError的使用详解

前言 useAsyncError 是 React Router v6.4 引入的一个钩子&#xff0c;用于处理异步操作&#xff08;如数据加载&#xff09;中的错误。下面我将详细解释其用途并提供代码示例。 一、useAsyncError 用途 处理异步错误&#xff1a;捕获在 loader 或 action 中发生的异步错误替…...

从零开始打造 OpenSTLinux 6.6 Yocto 系统(基于STM32CubeMX)(九)

设备树移植 和uboot设备树修改的内容同步到kernel将设备树stm32mp157d-stm32mp157daa1-mx.dts复制到内核源码目录下 源码修改及编译 修改arch/arm/boot/dts/st/Makefile&#xff0c;新增设备树编译 stm32mp157f-ev1-m4-examples.dtb \stm32mp157d-stm32mp157daa1-mx.dtb修改…...

图表类系列各种样式PPT模版分享

图标图表系列PPT模版&#xff0c;柱状图PPT模版&#xff0c;线状图PPT模版&#xff0c;折线图PPT模版&#xff0c;饼状图PPT模版&#xff0c;雷达图PPT模版&#xff0c;树状图PPT模版 图表类系列各种样式PPT模版分享&#xff1a;图表系列PPT模板https://pan.quark.cn/s/20d40aa…...

JVM虚拟机:内存结构、垃圾回收、性能优化

1、JVM虚拟机的简介 Java 虚拟机(Java Virtual Machine 简称:JVM)是运行所有 Java 程序的抽象计算机,是 Java 语言的运行环境,实现了 Java 程序的跨平台特性。JVM 屏蔽了与具体操作系统平台相关的信息,使得 Java 程序只需生成在 JVM 上运行的目标代码(字节码),就可以…...

【SSH疑难排查】轻松解决新版OpenSSH连接旧服务器的“no matching...“系列算法协商失败问题

【SSH疑难排查】轻松解决新版OpenSSH连接旧服务器的"no matching..."系列算法协商失败问题 摘要&#xff1a; 近期&#xff0c;在使用较新版本的OpenSSH客户端连接老旧SSH服务器时&#xff0c;会遇到 "no matching key exchange method found"​, "n…...

RabbitMQ入门4.1.0版本(基于java、SpringBoot操作)

RabbitMQ 一、RabbitMQ概述 RabbitMQ RabbitMQ最初由LShift和CohesiveFT于2007年开发&#xff0c;后来由Pivotal Software Inc.&#xff08;现为VMware子公司&#xff09;接管。RabbitMQ 是一个开源的消息代理和队列服务器&#xff0c;用 Erlang 语言编写。广泛应用于各种分布…...

Python+ZeroMQ实战:智能车辆状态监控与模拟模式自动切换

目录 关键点 技术实现1 技术实现2 摘要&#xff1a; 本文将介绍如何利用Python和ZeroMQ消息队列构建一个智能车辆状态监控系统。系统能够根据时间策略自动切换驾驶模式&#xff08;自动驾驶、人工驾驶、远程驾驶、主动安全&#xff09;&#xff0c;并通过实时消息推送更新车…...

MinIO Docker 部署:仅开放一个端口

MinIO Docker 部署:仅开放一个端口 在实际的服务器部署中,出于安全和管理的考虑,我们可能只能开放一个端口。MinIO 是一个高性能的对象存储服务,支持 Docker 部署,但默认情况下它需要两个端口:一个是 API 端口(用于存储和访问数据),另一个是控制台端口(用于管理界面…...

日常一水C

多态 言简意赅&#xff1a;就是一个对象面对同一事件时做出的不同反应 而之前的继承中说过&#xff0c;当子类和父类的函数名相同时&#xff0c;会隐藏父类的同名函数转而调用子类的同名函数&#xff0c;如果要调用父类的同名函数&#xff0c;那么就需要对父类进行引用&#…...