一篇文章搞定Java泛型

news2024/9/27 9:30:10

目录

介绍

优点

泛型类

语法定义

代码示例 

泛型类注意事项

 抽奖示例

 泛型类派生子类

定义

代码示例

子类是泛型

 子类不是泛型

 泛型接口

定义

泛型方法

定义

 代码示例

 泛型方法与可变参数

泛型方法总结 

​编辑类型通配符

定义 

 代码示例

通配符的上限 

定义

代码示例

通配符的下限 

定义

 代码示例

 jdk中下限通配符的使用

 类型擦除

泛型与数组 

泛型与反射 

定义

代码示例 


介绍

JAVA推出泛型以前,程序员可以构建一个元素类型为Object的集合,该集合能够存储任意的数据类型对象,而在使用该集合的过程中,需要程序员明确知道存储每个元素的数据类型,否则很容易引发ClassCastException异常。

Java泛型(generics)是JDK5中引入的一个新特性,泛型提供了编译时类型安全监测机制,该机制允许我们在编译时检测到非法的类型数据结构。

泛型的本质就是参数化类型,也就是所操作的数据类型被指定为一个参数。

优点

类型安全

消除了强制类型的转换

泛型类

语法定义

 

代码示例 

// <T> 泛型标识--类型形参  T创建对象的时候指定具体的数据类型
public class Generic<T> {
    //T 外部创建使用类的时候来指定  可以理解为 谁用谁定义
    private T key;

    public Generic() {}
    public Generic(T key) {
        this.key = key;
    }

    public T getKey() {
        return key;
    }

    public void setKey(T key) {
        this.key = key;
    }

    @Override
    public String toString() {
        return "Generic{" +
                "key=" + key +
                '}';
    }
}

 测试:

 注意泛型类不支持基本数据类型 这点在编译时就会有报警提示

泛型类注意事项

 抽奖示例

public class ProdocGetter<T> {

    Random random = new Random();

    //奖品
    private T product;

    //奖品池
    List<T> list = new ArrayList<>();

    //添加奖品
    public void addPro(T t){
        list.add(t);
    }

    //随机抽奖
    public T getProduct(){
        return list.get(random.nextInt(list.size()));
    }

    public static void main(String[] args) {
        //创建抽奖器对象 指定奖品类型(数据类型)
        ProdocGetter<String> stringProdocGetter = new ProdocGetter<>();
        String[] strings = {"苹果电脑","小米手机","奔驰汽车","迪迦奥特曼玩具"};
        //奖品池塞入奖品
        for (String pro : strings) {
            stringProdocGetter.addPro(pro);
        }
        //抽奖
        System.out.println("恭喜您,抽中了:"+stringProdocGetter.getProduct());

        System.out.println("分割线====================================");
        ProdocGetter<Integer> intProdocGetter = new ProdocGetter<>();
        Integer[] integers = {100,500,9000,16645,30458};
        //奖品池塞入奖品
        for (Integer pro : integers) {
            intProdocGetter.addPro(pro);
        }
        //抽奖
        System.out.println("恭喜您,抽中了:"+intProdocGetter.getProduct()+"元");

    }
}

测试:

 泛型类派生子类

定义

代码示例

子类是泛型

父类泛型

public class Parent<E> {
    private E value;

    public E getValue() {
        return value;
    }

    public void setValue(E value) {
        this.value = value;
    }
}

 子类泛型

//泛型类派生子类,子类也是泛型类,那么子类的泛型标识要和父类一致。
public class Child<T> extends Parent<T>{
    @Override
    public T getValue() {
        return super.getValue();
    }

    public static void main(String[] args) {
        Child<String> child = new Child<>();
        child.setValue("我是一个字符串");
        System.out.println(child.getValue());
    }
}

测试:

注意此时的子类泛型是T,继承的父类也是T,而最原先定义的父类泛型是E

子类如果是泛型,那么必须指定父类泛型和子类是一致的

如果不一致:

 子类不是泛型

//泛型类派生子类 如果子类不是泛型,那么父类需要明确指定数据类型 如果不指定那么数据类型则为Object
public class ChildSecond extends Parent<Integer>{
    @Override
    public Integer getValue() {
        return super.getValue();
    }

    @Override
    public void setValue(Integer value) {
        super.setValue(value);
    }

    public static void main(String[] args) {
        ChildSecond  childSecond = new ChildSecond();
        childSecond.setValue(1000);
        System.out.println(childSecond.getValue());
    }
}

测试:

 如果不明确指定父类的数据类型

 泛型接口

定义

 

 泛型接口的代码示例和泛型类派生子类如出一辙,不再代码示例

泛型方法

定义

 代码示例

 还是以之前的例子,但是这里需要多定义一个泛型方法

public class ProdocGetter<T> {

    Random random = new Random();

    //奖品
    private T product;

    //奖品池
    List<T> list = new ArrayList<>();

    //添加奖品
    public void addPro(T t){
        list.add(t);
    }

    //随机抽奖
    public T getProduct(){
        return list.get(random.nextInt(list.size()));
    }

    //定义泛型方法
    public <E> E getProduct(List<E> list){
        return list.get(random.nextInt(list.size()));
    }

    public static void main(String[] args) {
        ProdocGetter<Integer> prodocGetter = new ProdocGetter<>();
        List<String> strList = new ArrayList<>();
        strList.add("华为手机");
        strList.add("苹果手表");
        strList.add("空调");
        //泛型方法的调用 类型是通过调用方法的时候来指定
        String procut = prodocGetter.getProduct(strList);
        System.out.println(procut+"\t"+procut.getClass().getSimpleName());
        System.out.println("分割线=============================================>");
        ArrayList<Integer> integers = new  ArrayList<>();
        integers.add(100);
        integers.add(30004);
        integers.add(6471);
        Integer integer = prodocGetter.getProduct(integers);
        System.out.println(integer+"\t"+integer.getClass().getSimpleName());
    }
}

测试:

 定义多个泛型类型的静态泛型方法

 泛型方法与可变参数

 

泛型方法总结 

类型通配符

定义 

 代码示例

我们先看下数据类型Integer和Number的关系

点进Integer可以看到Integer是继承了Number

根据原先多态的想法,我们可以这样定义:

但是这里却报错了

也就是说泛型这里不可以使用多态来进一步转换类型数据,这个时候类型通配符的作用就显现出来了

通配符的上限 

定义

代码示例

书写三个继承关系类,Animal->BIgDog->Dog

Animal:

public class Animal {
}

 BIgDog:

public class BIgDog extends Animal{
}

Dog:

public class Dog extends BIgDog{
}

测试:

本次没有测试演示,可以看到此时定义的通配符上限类为BigDog,所以showAnimal中传递的集合数据类型只能由BigDog或者BigDog的子类,BigDog的父类Animal已经报警不可用

 

需要注意的是通配符上限的集合是不允许填充实例数据的,比如:

因为此时定义了通配符的上限类,而集合根本不确定集合中存的数据是什么数据类型

通配符的下限 

定义

 代码示例

 可以看到此时定义的通配符下限类为BigDog,所以showAnimals中传递的集合数据类型只能由BigDog或者BigDog的父类,BigDog的子类Dog已经报警不可用

通配符下限这里集合是可以直接添加实例的

 jdk中下限通配符的使用

改造三个类

Animal

public class Animal {
    public String name;

    public Animal(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "Animal{" +
                "name='" + name + '\'' +
                '}';
    }
}

BigDog

public class BIgDog extends Animal{

    public Integer age;

    public BIgDog(String name, Integer age) {
        super(name);
        this.age = age;
    }

    @Override
    public String toString() {
        return "BIgDog{" +
                "age=" + age +
                ", name='" + name + '\'' +
                '}';
    }
}

Dog

public class Dog extends BIgDog{

    public Integer level;

    public Dog(String name, Integer age, Integer level) {
        super(name, age);
        this.level = level;
    }

    @Override
    public String toString() {
        return "Dog{" +
                "level=" + level +
                ", age=" + age +
                ", name='" + name + '\'' +
                '}';
    }
}

TreeSet中的有一个构造函数就是典型的通配符下限使用

 测试:

 

 类型擦除

 

 

 

泛型与数组 

泛型与反射 

定义

代码示例 

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

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

相关文章

leetcode743. 网络延迟时间 floyd

https://leetcode.cn/problems/network-delay-time/ 有 n 个网络节点&#xff0c;标记为 1 到 n。 给你一个列表 times&#xff0c;表示信号经过 有向 边的传递时间。 times[i] (ui, vi, wi)&#xff0c;其中 ui 是源节点&#xff0c;vi 是目标节点&#xff0c; wi 是一个信…

详细介绍 React 中如何使用 redux

在使用之前要先了解它的配套插件&#xff1a; 在React中使用redux&#xff0c;官方要求安装其他插件 Redux Toolkit 和 react-redux Redux Toolkit&#xff1a;它是一个官方推荐的工具集&#xff0c;旨在简化 Redux 的使用和管理。Redux Toolkit 提供了一些提高开发效率的工具…

F5 LTM 知识点和实验 5-健康检测

第五章:健康检测 监控的分类: 地址监控(3层)服务监控(4层)内容监控(7层)应用监控(7层)性能监控(7层)路径监控(3、4、7层)三层监控: 三层监控可以帮助bipip系统通过检查网络是否可达监视资源。比如使用icmp echo,向监控节点发送icmp_echo报文,如果接收到响应…

求分享如何批量压缩视频的容量的方法

视频内存过大&#xff0c;不但特别占内存&#xff0c;而且还会使手机电脑出现卡顿的现象&#xff0c;除此之外&#xff0c;如果我们想发送这些视频文件可能还会因为内存太大无法发送。因此&#xff0c;我们可以批量地压缩视频文件的内存大小&#xff0c;今天小编要来分享一招&a…

车载软件架构 —— 信息安全与基础软件

车载软件架构 —— 信息安全与基础软件 我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 没有人关注你。也无需有人关注你。你必须承认自己的价值,你不能站在他人的角度来反对自己。人生在世,最怕…

郑州多域名https证书

多域名https证书是https证书中比较特殊的一款&#xff0c;它保护的域名记录是众多https证书中最灵活的。不管是DV基础型的多域名https证书还是OV企业型和EV增强型的多域名https证书既可以保护多个主域名或者子域名&#xff0c;还可以主域名子域名随意组合&#xff0c;只要申请者…

matlab--solve函数的用法

目录 1.用法结构 2.解单变量方程 3.解多变量方程 4.解带参方程 5.解不等式 6.总结 1.用法结构 solve函数是MATLAB中的一个符号计算函数&#xff0c;用于求解方程组或方程的符号解。 它的用法如下&#xff1a; 定义符号变量&#xff1a;使用syms函数定义符号变量&#…

CSDN博客置顶操作

目录 背景: 过程: 第一步: 第二步&#xff1a; 总结&#xff1a; 背景: 对于文章博主都想把优质的好文放在第一位与大家分享&#xff0c;让更多的人看到自己的文章以便更好的展现出来&#xff0c;那么就是置顶。 过程: 第一步: 打开CSDN主页文章&#xff0c;将鼠标放在…

css定义超级链接a标签里面的title的样式

效果: 代码: 总结:此css 使用于任何元素,不仅仅是a标签!

找不到mfc140u.dll怎么解决

第一&#xff1a;mfc140u.dll有什么用途&#xff1f; mfc140u.dll是Windows操作系统中的一个动态链接库文件&#xff0c;它是Microsoft Foundation Class (MFC)库的一部分。MFC是 C中的一个框架&#xff0c;用于构建Windows应用程序的用户界面和功能。mfc140u.dll包含了MFC库中…

12. Mybatis 多表查询 动态 SQL

目录 1. 数据库字段和 Java 对象不一致 2. 多表查询 3. 动态 SQL 使用 4. 标签 5. 标签 6. 标签 7. 标签 8. 标签 9. 通过注解实现 9.1 查找所有数据 9.2 通过 id 查找 1. 数据库字段和 Java 对象不一致 我们先来看一下数据库中的数据&#xff1a; 接下来&#…

冠达管理:股指预计维持震荡格局 关注汽车、酿酒等板块

冠达管理指出&#xff0c;周四A股商场冲高遇阻、小幅震动整理&#xff0c;早盘股指高开后震动上行&#xff0c;沪指盘中在3245点邻近遭遇阻力&#xff0c;午后股指逐级回落&#xff0c;轿车、金融、酿酒以及军工等职业轮番领涨&#xff0c;互联网、软件、半导体以及证券等职业震…

Git克隆文件不显示绿色勾、红色感叹号等图标

1、问题 Git和TorToiseGit安装后&#xff0c;Git克隆的文件不会显示绿色勾、红色感叹号等图标。 2、检查注册表 2.1、打开注册表 (1)WinR打开运行窗口&#xff0c;输入regedit&#xff0c;点击确定&#xff0c;打开注册表编辑器。 2.2、找如下路径 (1)找到路径 计算机\HKEY_…

Unity 性能优化四:UI耗时函数、资源加载、卸载API

UI耗时函数 1.1 Canvas.SendWillRenderCanvases 这个函数是由于自身UI的更新&#xff0c;产生的耗时 1. 这里更新的是vertex 属性&#xff0c;比如 color、tangent、position、uv&#xff0c;修改recttransform的position、scale&#xff0c;rotation并不会导致顶点属性改变…

想测试入门就必须要懂的软件开发流程

从事软件测试行业&#xff0c;每天面对的被测对象都是软件。如果想要更好的去完成测试工作&#xff0c;首先需要对被测对象&#xff0c;也就是对软件要有基本的了解。 软件 与计算机系统操作有关的计算机程序、可能有的文件、文档及数据。 程序好理解&#xff0c;就是可以操…

JS正则表达式:常用正则手册/RegExp/正则积累

一、正则基础语法 JavaScript 正则表达式 | 菜鸟教程 JS正则表达式语法大全&#xff08;非常详细&#xff09; 二、使用场景 2.1、校验中国大陆手机号的正则表达式 正则 /^1[3456789]\d{9}$/解释 序号正则解释1^1以数字 1 开头2[3456789]第二位可以是 3、4、5、6、7、8、…

MybatisPlus拓展篇

文章目录 逻辑删除通用枚举字段类型处理器自动填充功能防全表更新与删除插件MybatisX快速开发插件插件安装逆向工程常见需求代码生成 乐观锁问题引入乐观锁的使用效果测试 代码生成器执行SQL分析打印多数据源 逻辑删除 逻辑删除的操作就是增加一个字段表示这个数据的状态&…

本地仓库推送至远程仓库

1. 本地生成ssh密钥对 ssh-keygen -t rsa -C 邮箱2. 添加公钥到gitlab/github/gitee上 打开C:\Users\用户名\.ssh目录下生成的密钥文件id_rsa.pub&#xff0c;把内容复制到如下文本框中 删除Expiration date显示的日期&#xff0c;公钥有效期变成永久&#xff0c;之后点Add K…

LeetCode 刷题 数据结构 数组 485 最大连续1的个数

给定一个二进制数组 nums &#xff0c; 计算其中最大连续 1 的个数。 示例 1&#xff1a; 输入&#xff1a;nums [1,1,0,1,1,1] 输出&#xff1a;3 解释&#xff1a;开头的两位和最后的三位都是连续 1 &#xff0c;所以最大连续 1 的个数是 3.示例 2: 输入&#xff1a;nums […

ROS中使用RealSense-D435

文章目录 D435简介RealSense的SDK2.0安装方法1&#xff1a;直接利用安装源安装注册服务器公匙将服务器添加到存储库列表安装库 方法2&#xff1a;利用源码安装GitHub下载librealsense安装编译依赖运行脚本cmake编译 软件显示 ROS接口安装启动节点查看话题rviz显示点云 Python接…