限制泛型类型、使用类型通配符和继承泛型类(接口)

news2024/11/25 2:43:05

文章目录

  • 前言
  • 一、限制泛型类可用类型
  • 二、使用类型通配符(?)
  • 三、继承泛型类与实现泛型接口
  • 总结

前言

        本篇介绍泛型类的更深层次的用法,限制泛型定义数据类型的范围、使用类型通配符、继承泛型类与实现泛型接口。


一、限制泛型类可用类型

        泛型类的类型限制是指在定义泛型类时通过使用extends关键字来限制可用的类型范围。泛型可以继承。

 设定泛型的上限,语法如下:

class 类名<T extends anyClass>    

        调用了 extends关键字 ,继承某类,那么只能使用这个类及其子类充当泛型。

         实操展示:使用extends关键字,将TestDemo类的泛型继承自Colloection类及其子类

import java.util.Collection;
import java.util.List;
import java.util.Set;

public class TestDemo<T extends Collection>{ 
    public static void main(String[] args) {
        TestDemo<Set> testDemo = new TestDemo<>();
        TestDemo<List> testDemo2 = new TestDemo<>();
        TestDemo<Collection> testDemo3 = new TestDemo<>();
        //在创建泛型时只能创建Collection以及其子类
    }
}

         如上代码所示,当TestDemo类继承了Colloection类,当实例化对象时,必须实现泛型该类或者其类的子类。由于map集合不是Collection的子类,如果泛型化map集合类,则会报错。

二、使用类型通配符(?)

        泛型机制中,提供了通配符,其主要作用为限制这个泛型类对象的类型实现或者继承某一接口或者类的子类。类型通配符为“?” ,同时使用 extends 或者 super 关键字加以限制。

        通配符有以下几种形式:

        1.未限定通配符(?):表示未知类型,可以匹配任意类型的实参。

        2.上限通配符(? extends 类型):表示未知类型是指定类型的子类,可以匹配指定类型或其子类的实参。

        3.下限通配符(? super 类型):表示未知类型是指定类型的父类,可以匹配指定类型或其父类的实参。

        类型通配符不能写在创建泛型类当中。

        以下是使用泛型通配符的语法如下:

泛型类名<?> 对象 = null;
//泛型类型未知

泛型类名<? extends anyClass> 对象1 = null;
//对象1的泛型只能是anyClass以及anyClass的子类

泛型类名<? super anyClass> 对象2 = null;
//对象2的泛型只能是anyClass以及anyClass的父类

        使用上面的语法时,自身类必须设定了泛型<T>。 

        实操展示:设置Demo实例化对象的泛型为继承List集合的子类

Demo<? extends List> demo = null,demo2= null;    //使用语法

demo = new Demo<ArrayList>();
ArrayList<String> arrayList = demo.getObject();
arrayList.add("Hello");
arrayList.add("World");

demo2 = new Demo<LinkedList>();
LinkedList<Integer> linkedList = demo2.getObject();
linkedList.add(1);
linkedList.add(2);

//demo 和 demo2 都泛型类实现了List集合类的子类

         由上代码所示通配符的使用,使用通配符可以使得泛型类或方法能够处理更多类型的参数,提高代码的复用性和可扩展性。另外,在涉及类型转换或泛型类型的不确定性时,使用通配符可以避免编译器的类型检查错误。但值得注意的是,一旦使用了泛型通配符,集合中的值就不能改变了。super下限通配符的用法和注意点和上面一样,区别只是泛型化了super后的类型及其父类。

三、继承泛型类与实现泛型接口

        继承泛型的四种情况:

        (1)全部继承·:

abstract class Father<T1,T2>{}
//父类

class Child<T1,T2,T3> extends Father<T1,T2>{}
//继承全部父类泛型

         Child类继承Father类时保留父类的泛型类型,需要在继承时指明。如果没有指明,直接使用 extends关键字继承操作,那么 Child类中的泛型T1,T2,T3都默认为Object类。所以1一般情况都将父类的泛型类指明保留。 

        实操展示:创建Father类和Child类,创建构造方法,分别用向上转型和子类实例化来演示了泛型类的使用和继承关系。

import java.lang.Math;
public class TestDemo{ 
    public static void main(String[] args) {
        Father<Integer,Double> father = new Child(1024, Math.PI);
        System.out.println("--------------------------------");
        Child<Integer,Double,String> child = new Child(404, "错误");
    }
}

class Father<T1,T2> {
    T1 t1;
    T2 t2;

    public Father(T1 t1,T2 t2){
        this.t1=t1;
        this.t2=t2;
        System.out.println("t1的类型:"+this.t1.getClass());
        System.out.println("t2的类型:"+this.t2.getClass());
    }
}

//Father类中此处的T3传参的是Father类原本的T2,调用构造方法时t2填写T3类型的数据
class Child<T1,T2,T3> extends Father<T1,T3>{
    public Child(T1 t1,T3 t2){
        super(t1, t2);
    }
}

        运行结果:

 

        由上图所示, 第一种向上转型,父类直接明确数据的类型,子类实例化内容后赋值给了父类对象;第二种子类实例化,子类的第一个和第三个泛型类型是构造方法的串参类型,输入类型为子类明确的T1和T3类型。

         (2)部分继承:

abstract class Father<T1,String>{}
//父类

class Child<T1,T2,T3> extends Father<T1,String>{}
//继承部分父类泛型

         之所以说是部分继承泛型,是因为子类Child只继承了父类Father的部分泛型类型T1,T2的类型已经被明确为String,因此在声明Child对象时只需要提供T1的具体类型。这样做的目的是为了灵活使用泛型,根据具体情况确定需要继承的泛型类型。

         实操展示:明确Father类的部分泛型,让其他部分的泛型被Child继承

public class lon {
    public static void main(String[] args) {
        Child<Boolean,Double,Boolean> child = new Child( true, "字符串");
        Child<Double,Double,Boolean> child2 = new Child( 3.14, "字符串");
    }
     
}

class Father<T1,T2>{
    T1 t1;
    T2 t2;
    public Father(T1 t1,T2 t2){
        this.t1=t1;
        this.t2=t2;
        System.out.println("t1的类型:"+this.t1.getClass());
        System.out.println("t2的类型:"+this.t2.getClass());
    }
}

//Child类继承了Father类的泛型T1
class Child<T1,T2,T3>extends Father<T1,String>{
    public Child(T1 t1,String t2){
        super(t1, t2);
    }
}

         运行结果:

        由上图所示,若是子类部分继承父类的泛型,意思是父类在被继承的过程中实现了一部分泛型,另一部分的泛型类型还没有确定,这部分没确定的泛型会被子类灵活使用,或为布尔值,或为浮点数等。 

        (3) 实现父类泛型:

abstract class Father<T1,T2>{}
//父类

class Child<T1,T2> extends Father<Integer,String>{}
//继承部分父类泛型

         实现父类泛型是指在子类中使用父类的泛型类型。继承父类的过程中,明确父类的泛型类型,子类进行实现父类的泛型类型,不定义其泛型类型。

        实操展示:在Child类继承Father类的过程中,明确Father类两个泛型的数据类型,使子类实现父类泛型。

public class lon {
    public static void main(String[] args) {
        Child<Boolean,Double,Boolean> child = new Child( 1, 1.12);
        System.out.println("------------------------------------");
        Child<Double,Double,Boolean> child2 = new Child( 3, 1.13);
    }
     
}

class Father<T1,T2>{
    T1 t1;
    T2 t2;
    public Father(T1 t1,T2 t2){
        this.t1=t1;
        this.t2=t2;
        System.out.println("t1的类型:"+this.t1.getClass());
        System.out.println("t2的类型:"+this.t2.getClass());
    }
}
//设置的父类泛型为 Integer和Double,子类构造方法只能是这两种类型,不能改变继承的泛型
class Child<T1,T2,T3>extends Father<Integer,Double>{
    public Child(Integer t1,Double t2){
        super(t1, t2);
    }
}

        设置的父类泛型为 Integer和Double,子类构造方法只能是这两种类型,不能改变继承的泛型 

        运行结果:

 

         (4)不实现父类泛型:

abstract class Father<T1,String>{}
//父类

class Child extends Father{}
//不实现父类泛型

        不实现父类泛型,因此所有的父类泛型类型都会变为Object类型,那么子类Child在调用父类的一切方法,参数都可以自定义类型,没有约束。 

         实操展示:

public class lon {
    public static void main(String[] args) {
        Child<Boolean,Double,Boolean> child = new Child( new Object(), 1.12);
        System.out.println("------------------------------------");
        Child<Double,Double,Boolean> child2 = new Child( 3, true);
    }
     
}

class Father<T1,T2>{
    T1 t1;  //Object t1;
    T2 t2;  //Object t2;
    public Father(T1 t1,T2 t2){
        this.t1=t1; 
        this.t2=t2;
        System.out.println("t1的类型:"+this.t1.getClass());
        System.out.println("t2的类型:"+this.t2.getClass());
    }
}

class Child<T1,T2,T3>extends Father{
    public Child(Object t1,Object t2){
        super(t1, t2);
    }
}

        运行结果:

 

        由上图所示,不实现父类泛型,父类Father的所有参数都变成了初始的Object类,子类Child可以在调用父类方法时,任意创建各种类型的数据参数。可以为Object对象,也可以使浮点数等。 


总结

        泛型的类型参数只能是类类型,不可以使简单类型,例如<long>这种泛型定义就是错误的。在本篇不少实例中不难看出,定义泛型时,可以是多个的;可以使用extends关键字或者通配符(?)来限制泛型的类型。

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

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

相关文章

winform2

12.TabControl 导航控制条 using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; namespace zhiyou_…

爆!Java高级特性之Stream API详解

爆&#xff01;Java高级特性之Stream API详解 Java 8引入的Stream API可以说是一个革命性的特性,让我们告别了又臭又长的for循环,迎来了函数式编程的春天。今天就让我们来一起深入了解这个让人又爱又恨的Stream API吧! 什么是Stream? Stream就像一个高级的迭代器,允许我们以…

应用了网络变压器的PC网卡连接转换器后不好连网,有掉线现象,但外接路由器无问题,可能是什么原因?

Hqst盈盛&#xff08;华强盛&#xff09;电子导读&#xff1a;今天分享的是应用了网络变压器的PC网卡连接转换器后不好连网&#xff0c;有掉线现象&#xff0c;但外接路由器无问题&#xff0c;可能是什么原因呢&#xff1f;如何解决呢&#xff1f; 首先&#xff0c;我们要了解传…

无人机常见故障及维修方法详解

一、无人机故障识别与处理原则 无人机故障识别是维修的第一步&#xff0c;要求操作人员具备基本的无人机系统知识和故障识别能力。在识别故障时&#xff0c;应遵循“先易后难、先外后内、先软件后硬件”的原则。一旦识别出故障&#xff0c;应立即停止飞行&#xff0c;避免进一…

【VUE基础】VUE3第三节—核心语法之computed、watch、watcheffect

computed 接受一个 getter 函数&#xff0c;返回一个只读的响应式 ref 对象。该 ref 通过 .value 暴露 getter 函数的返回值。它也可以接受一个带有 get 和 set 函数的对象来创建一个可写的 ref 对象。 创建一个只读的计算属性 ref&#xff1a; <template><div cl…

Java项目:基于SSM框架实现的校园快递代取管理系统【ssm+B/S架构+源码+数据库+毕业论文】

一、项目简介 本项目是一套基于SSM框架实现的校园快递代取管理系统 包含&#xff1a;项目源码、数据库脚本等&#xff0c;该项目附带全部源码可作为毕设使用。 项目都经过严格调试&#xff0c;eclipse或者idea 确保可以运行&#xff01; 该系统功能完善、界面美观、操作简单、…

树莓派+舵机+pca9685+usb摄像头制作二维云台,图像追踪

使用树莓派+舵机+pca9685+usb摄像头制作二维云台,图像追踪 为什么使用pca9685驱动舵机,而不使用树莓派自带的引脚驱动舵机呢? 因为树莓派无法产生稳定的pwm波,容易造成舵机的抖动 我使用的是树莓派+ubuntu系统+pca9685 1.首先在ubuntu系统中安装相关依赖 sudo apt insta…

海尔智家:科技优秀是一种习惯

海尔智家&#xff1a;科技优秀是一种习惯 2024-06-28 15:19代锡海 6月24日&#xff0c;2023年度国家科学技术奖正式揭晓。海尔智家“温湿氧磁多维精准控制家用保鲜电器技术创新与产业化”项目荣获国家科学技术进步奖&#xff0c;成为家电行业唯一牵头获奖企业。 很多人说&…

odoo 物联网 设备数据采集方案

图一 架构手稿(许老师专属) 图二 架构简图 部署 方案一&#xff1a; odoo业务数据库与设备采集数据库使用一个instance。 缺点&#xff1a;重启pg服务相互影响。 方案二&#xff1a; odoo业务数据库与设备采集数据库独立部署&#xff0c;使用两个instance。 优点&#xff1a;…

VSCode远程服务器

一、安装VSCode Windows安装Visual Studio Code(VS Code)-CSDN博客 二、VSCode中安装Remote-SSH插件 1、在应用商店中搜索Remote - SSH并安装 2、安装后会出现下面标注的图标 三、开始SSH连接 1、点击加号&#xff0c;创建SSH连接 2、输入地址&#xff0c;格式是&#xff1a;…

java集合(1)

目录 一.集合概述 二. 集合体系概述 1. Collection接口 1.1 List接口 1.2 Set接口 2. Map接口 三. ArrayList 1.ArrayList常用方法 2.ArrayList遍历 2.1 for循环 2.2 增强for循环 2.3 迭代器遍历 一.集合概述 我们经常需要存储一些数据类型相同的元素,之前我们学过…

RocketMQ-订阅一致及解决方案

背景 这里借用Rocketmq官方的一句话来描述订阅关系一致: 订阅关系一致指的是同一个消费者分组Group ID下&#xff0c;所有Consumer实例所订阅的Topic和Tag必须完全一致。如果订阅关系不一致&#xff0c;可能导致消息消费逻辑混乱&#xff0c;消息被重复消费或遗漏。 具体的问题…

MySQL中mycat与mha应用

目录 一.Mycat代理服务器 1.Mycat应用场景 2.mycat安装目录结构说明 3.Mycat的常用配置文件 4.Mycat日志 5.mycat 实现读写分离 二.MySQL高可用 1.原理过程 2.MHA软件 3.实现MHA 一.Mycat代理服务器 1.Mycat应用场景 Mycat适用的场景很丰富&#xff0c;以下是几个典型…

【Java11】变量的初始化和内存中的运行机制

成员变量的初始化和内存中的运行机制 系统加载类或创建类的实例时&#xff0c;系统自动为成员变量分配内存空间&#xff0c;然后自动为成员变量指定初始值。 class Person {public String name; // 实例变量public static int eyeNum; // 类变量 }var p1 Person(); var p2 …

【unity实战】Unity中使用A*寻路+有限状态机制作一个俯视角敌人AI

最终效果 文章目录 最终效果前言A*寻路插件介绍下载导入AI插件生成寻路网格节点的类型障碍物寻路测试A*只打印报错信息 代码控制寻路动画配置敌人状态机各种状态脚本效果完结 前言 前面做过有限状态机制作一个敌人AI&#xff1a;【unity实战】在Unity中使用有限状态机制作一个…

【Odoo开源ERP】别把ERP与进销存软件混为一谈

导读&#xff1a;企业使用ERP软件能够实现管理升级&#xff0c;多方信息集成&#xff0c;按照既定策略逻辑运算&#xff0c;生成计划建议&#xff0c;减少人力成本&#xff0c;提高准确率的同时提高经营能力。 ERP&#xff0c;是MRP II的下一代软件&#xff0c;除了MRP II已有的…

WEB安全-靶场

1 需求 2 语法 3 示例 男黑客|在线渗透测试靶场|网络安全培训基地|男黑客安全网 4 参考资料

三万字带你一遍跑通uer

三万字带你一遍跑通uer 参考文档 今天给大家介绍个非常强大的项目uer&#xff0c;集成了许多可以做自然语言的东西&#xff0c;效果的话也非常好&#xff0c;很适合企业级的应用&#xff01; 1. 先将项目uer从github拉取下来&#xff08;zip或git都ok&#xff09; 2. 用pycha…

Vue88-Vuex中的mapActions、mapMutations

一、mapMutations的调用 此时结果不对&#xff0c;因为&#xff1a;若是点击事件不传值&#xff0c;默认传的是event&#xff01;&#xff0c;所以&#xff0c;修改如下&#xff1a; 解决方式1&#xff1a; 解决方式2&#xff1a; 不推荐&#xff0c;写法麻烦&#xff01; 1-…

【代码大全2 选读】看看骨灰级高手消灭 if-else 逻辑的瑞士军刀长啥样

文章目录 1 【写在前面】2 【心法】这把瑞士军刀长啥样3 【示例1】确定某个月份的天数&#xff08;Days-in-Month Example&#xff09;4 【示例2】确定保险费率&#xff08;Insurance Rates Example&#xff09;5 【示例3】灵活的消息格式&#xff08;Flexible-Message-Format …