六、Java高级-泛型(二)

2、泛型的实现

2.1 泛型的使用

1、类或接口后面→泛型类/泛型接口(参数化的类型)

  • 当类中的某个成员变量不确定时,可以考虑在类的上面声明泛型;当类/接口中某个非静态方法的形参或返回值不确定时。
  • 当类或接口中的某个/某些非静态方法的形参返回值类型不确定时,可以考虑在类/接口上声明泛型来表示这个未知的类型。如果多个方法都使用了类/接口上面声明的泛型,它们的类型是一致的。
//java.lang.comparable接口:
public interface Compareble<T> {public int compare(T o);//不是泛型方法
}
//java.util.Comparator:int compare(T t1,T t2)

2、方法的返回值类型前面→泛型方法

  • 当某个方法在设计时,它的形参、返回值不确定时,需要调用才能确定时,可以使用泛型方法。eg:复制任意类型的数组的方法。
//java.util.Arrays类
public static <T> List<T> asList(T... a){....
}
  • asList方法返回的是一个只读的集合,不能删除、添加元素(报错)
List<String> list = Arrays.asList("hello","world","zhang","san");
list.add("wangwu");//UnsupportedOprationException
list.removw("san");//UnsupportedOprationException
  • list不是ArrayList类型,而是ArrayList里面的一个私有内部类( java.util.Array&ArrayList),并没有add()\remove()方法
//复制一个数组
public static <T> T[] copyOf(T[] original,int length);
  • 每一个泛型方法声明的<T>都是独立的,与其他方法无关。方法在调用时,会根据实参类型自动推断<T>的具体类型。
  • 在类/接口上声明的泛型类型<T>不能用于静态方法不能用于静态成员/静态方法,因为T类型和对象有关。在static修饰符后面加一个<T>
class MyGenrics<T>{public void method(T t){...}public void fun(T t){...}//上面两个方法的T是一致的public static void test1(T t){...}//报错,T类型与MyGenrics对象有关public static <T> void test2(T t){...}//test2方法的T类型与MyGrics对象无关,与上面的T类型是相互独立的,相当于:// public static <K> void test(K k){...}
}
2.2 类型变量的上限
  • <T extends 上限>:T的类型必须是<=上限,要么是上限本身,要么继承上限类型。
  • <T extends 类 & 接口1 &接口2& …>:一个类型变量的上限可以是一个也可以是多个,但只能有一个类上限,且类在左边,其他类型上限在右边
Class Student<T extends Number & Comparable & ...>{...}
  • JVM在运行是不支持泛型类型的识别
2.3 泛型的擦除(eraser)
  • 如果用户在使用泛型类或泛型接口时,没有使用指定泛型的类型,就会发生泛型的擦除,将泛型转为非泛型。
  • 泛型擦除后,自动按照类型变量声明时的第一个上限进行处理,如果没有指定参数类型的上限,上限为Object。eg:List<Integer>和ListString<String>在运行时都会转为List类型。

泛型并不是由虚拟机执行的,而是在编译时实行的。JVM并不能识别泛型,如果没有指定<T>的类型,编译器会将<T>视为Object类型进行处理,并可以根据<T>的类型自动实现安全的强制转换。

  • <T>不能是基本数据类型(Object类型无法拥有基本类型)
  • 不能取得带泛型的Class,也不能判断泛型的类型
  • 不能实例化T类型→借助Class<T>参数并通过反射来实例化T类型
Student<String> stu1 = new Student<>(String.class);

3、泛型的继承关系

  • 泛型类、泛型接口和泛型类型之间的关系

1、泛型类、泛型接口的继承关系

在泛型类和泛型接口继承和实现的过程中,子类可以获取父类的泛型类型<T>

子类继承泛型父类时,子接口继承泛型父接口、或实现类实现泛型父接口时:

  • 指定类型变量对应的实际类型参数,此时子类或实现类不再是泛型类
class Student<T>{private String name;private T score;...
}
//Primary不是泛型类
class Primary extends Student<String>{...
}
  • 指定类型变量,此时子类、子接口、实现类仍然是泛型类或泛型接口
class Senior extends<E> extends Student<E>{...
}

2、泛型类型之间的继承关系

在Java中,泛型是不可变的,即泛型类型之间没有继承关系,即使它们的类型参数之间存在父子关系。所以Student<Integer>Student<Number>之间不是继承关系,而是不同类型的泛型类型。

Student<Integer> stu1 = new Student<>(100);
Student<Number> stu2 = inStu;//发生类型转换,但是编译报错classCastException

虽然Integer是Number的子类,但是Studeny<Integer>无法赋值给Student<Number>,stu1和stu2都指向同一个对象,即stu1所指向的对象。Java中的泛型是不可变的,stu2只能访问该对象的Number类型的方法和属性,而不能访问Integer类型的方法和属性。

并且,泛型通过类型擦除实现的,在编译后,Student<Integer>Student<Number>都被擦除为Student类型,编译器不能保证类型的一致性。

4、通配符

什么情况下使用?

当声明了一个变量/形参时,这个变量/形参的类型是一个泛型类或泛型接口,但还是不能确定这个泛型类/泛型接口的类型变量<T>的具体类型→ 类型通配符 ?

4.1 三种形式

1、<?>:?代表任意类型

2、<? extends 上限> :?代表<=上限类型

  • 该泛型类中所有参数是T类型的方法或成员都无法正常使用。参数类型不是T类型的方法照常使用。

3、<? supur 下限>:?代表>=下限类型

  • 该泛型类中所有参数是T类型的方法或成员都可以使用,但是有要求。参数类型不是T类型的方法照常使用。
<? extends Number>
Collection<?> coll = new ArrayList<>();
coll.add("hello");//报错
coll.add(1);//报错
coll.add(1.0);//报错
<?>:泛型类型未知,不能确定集合的元素`void add(E t)`方法中E由?表示,直到add方法被调用时,也不能确定E的类型。
Collection<? extends Number> coll = new ArrayList<Double>();
coll.add(1.0);//报错

2、<? extends 上限> :?代表<=上限类型

  • 该泛型类中所有参数是T类型的方法或成员都无法正常使用。参数类型不是T类型的方法照常使用。

3、<? supur 下限>:?代表>=下限类型

  • 该泛型类中所有参数是T类型的方法或成员都可以使用,但是有要求。参数类型不是T类型的方法照常使用。
<? extends Number>
Collection<?> coll = new ArrayList<>();
coll.add("hello");//报错
coll.add(1);//报错
coll.add(1.0);//报错

1、<?>:泛型类型未知,不能确定集合的元素void add(E t)方法中E由?表示,直到add方法被调用时,也不能确定E的类型。

Collection<? extends Number> coll = new ArrayList<Double>();
coll.add(1.0);//报错

2、<? extends Number>:泛型类型限定为Number及其子类。void add(E t)方法中<E><? extends Number>表示,但是直到add方法被调用时,也不能确定E的类型,可以是<=Number的任意一种类型。

Collection<? super Number> coll = new ArrayList<>();
coll.add(1);
coll.add(1.0);
coll.add("hello");//报错

3、<? super Number>:可以添加Number对象或Number子类对象。

PECS原则

PECS原则:Producer Extends Consumer Super。如果需要返回T,它是生产者(Producer),使用extends通配符;如果需要写入T,它是消费者(Consumer),使用super通配符。

public static <T> void copy(List<? super T> dest, List<? extends T> src) {for (int i=0; i<src.size(); i++) {T t = src.get(i); // src是producerdest.add(t); // dest是consumer}
}
4.2 注意的问题

1、<?>

如果某个泛型类/接口<T>在使用时,泛型指定为<?>,里面所有使用T类型声明的方法都不能正常使用(不能读也不能写,可以判断null类型)

2、<? extends 上限>

如果某个泛型类/接口<T>在使用时,泛型指定为<? extends 上限>,里面所有使用T类型声明的方法都不能正常使用(只能读也不能写,传入null除外[异常])

2、<? supur 下限>

如果某个泛型类/接口<T>在使用时,泛型指定为<? supur 上限>,里面所有使用T类型声明的方法都可以正常使用,但不能超过下限的类型(只能写也不能读,获取Object除外)

public class Collections {// 把src的每个元素复制到dest中:public static <T> void copy(List<? super T> dest, List<? extends T> src) {for (int i=0; i<src.size(); i++) {T t = src.get(i);dest.add(t);}}
}
  • copy()方法内部不会读取dest,因为不能调用dest.get()来获取T的引用;
  • copy()方法内部也不会修改src,因为不能调用src.add(T)。

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

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

相关文章

VueCLI核心知识3:全局事件总线、消息订阅与发布

这两种方式都可以实现任意两个组件之间的通信 1 全局事件总线 1.安装全局事件总线 import Vue from vue import App from ./App.vueVue.config.productionTip false/* 1.第一种写法 */ // const Demo Vue.extend({}) // const d new Demo()// Vue.prototype.x d // 把Dem…

【算法】树状数组和线段树

文章目录 一、树状数组二、线段树 一、树状数组 O ( l o g n ) O(logn) O(logn) &#xff1a;单点修改、区间查询 与前缀和的区别&#xff1a; 前缀和是离线的&#xff0c;每次动态修改原数组某个元素&#xff0c;都需要重新求一遍前缀和&#xff0c;因此单点修改是 O ( n )…

RK3568平台开发系列讲解(实验篇)用户空间和内核空间数据交换

🚀返回专栏总目录 文章目录 一、用户空间和内核空间数据交换二、实验驱动代码三、应用测试代码沉淀、分享、成长,让自己和他人都能有所收获!😄 一、用户空间和内核空间数据交换 内核空间和用户空间的内存是不能互相访问的。但是很多应用程序都需要和内核进行数据的交换,…

【AI视野·今日NLP 自然语言处理论文速览 第七十八期】Wed, 17 Jan 2024

AI视野今日CS.NLP 自然语言处理论文速览 Wed, 17 Jan 2024 (showing first 100 of 163 entries) Totally 100 papers &#x1f449;上期速览✈更多精彩请移步主页 Daily Computation and Language Papers Deductive Closure Training of Language Models for Coherence, Accur…

Mamba-UNet:用于医学图像分割的类似UNet的纯视觉Mamba网络

文章目录 摘要1、引言2、方法2.1、架构概述2.2、VSS 块2.3、编码器2.4、解码器2.5、瓶颈和跳跃连接3、实验与结果3.1、数据集3.2、实现细节3.3、基准方法3.4、评估指标3.5、定性结果3.6、定量结果4、结论摘要 在医学图像分析的最新进展中,卷积神

【手写数据库toadb】数据字典缓存的实现方法和接口分享,面向对象设计思想,接口单一化

412数据字典的缓存 ​专栏内容: 手写数据库toadb 本专栏主要介绍如何从零开发,开发的步骤,以及开发过程中的涉及的原理,遇到的问题等,让大家能跟上并且可以一起开发,让每个需要的人成为参与者。 本专栏会定期更新,对应的代码也会定期更新,每个阶段的代码会打上tag,方便…

优化策略模式,提高账薄显示的灵活性和扩展性

接着上一篇文章&#xff0c;账薄显示出来之后&#xff0c;为了提高软件的可扩展性和灵活性&#xff0c;我们应用策略设计模式。这不仅仅是为了提高代码的维护性&#xff0c;而是因为明细分类账账薄显示的后面有金额分析这个功能&#xff0c;从数据库后台分析及结合Java语言特性…

2023年中国网络安全产业发展态势

文章目录 前言一、需求依然增长,市场竞争加剧二、产业增速放缓,融资市场降温三、产业结构变革,优化整合途径(一)电信运营商快速入场,互联网厂商加速网络安全领域布局。(二)网络安全商业模式在发生变化,网络安全运营服务、托管服务模式正在逐渐被客户认同。(三)国内安…

gorm day7

gorm day7 gorm Belongs To关系gorm Has One关系 gorm Belongs To关系 在看文档之前先进行一些基本概念的学习&#xff1a; 什么是主键&#xff1f;&#xff08;Primary Key) 主键是一个表中的特定列&#xff08;或一组列&#xff09;&#xff0c;用来唯一标识表中的每一行记…

每日一个脚本之一键部署Docker

每日一个shell脚本之一键部署Docker 源码参上 #!/usr/bin/bash # **************************************# CSDN: M乔木 # qq邮箱: 2776617348qq.com # 解释器: 这是一个shell脚本 # *************************…

1.合唱队形

Problem: 1.合唱队形 文章目录 思路解题方法复杂度Code 思路 这是一个动态规划问题。我们可以通过两次动态规划来解决这个问题。首先&#xff0c;我们从左到右进行动态规划&#xff0c;计算出每个位置的最长递增子序列长度。然后&#xff0c;我们从右到左进行动态规划&#xff…

2024幻兽帕鲁服务器创建教程_阿里PK腾讯超简单

幻兽帕鲁官方服务器不稳定&#xff1f;自己搭建幻兽帕鲁服务器&#xff0c;低延迟、稳定不卡&#xff0c;目前阿里云和腾讯云均推出幻兽帕鲁专用服务器&#xff0c;腾讯云直接提供幻兽帕鲁镜像系统&#xff0c;阿里云通过计算巢服务&#xff0c;均可以一键部署&#xff0c;鼠标…

vscode 提取扩展时出错。XHR failed

检查 vscode 设置中的代理服务器&#xff0c;位置如下图 清空 vocode 中的 Proxy&#xff0c;我黄线框的部分&#xff0c;内容清空。 检查电脑系统环境变量&#xff0c;是否设置了 http_proxy 和 https_proxy&#xff0c;如果有设置&#xff0c;则删除这两项&#xff0c;下载完…

leetcode 102.二叉树的层序遍历

这道题讲的就是对于树的数据结构的考察&#xff0c;这里用了一个比较常用的容器就是队列。 思路&#xff1a;首先我们知道&#xff0c;层序遍历也就是广度优先遍历的一种变形而已&#xff0c;既然我们知道广度优先搜索&#xff0c;就应该知道用队列进行辅助输出。 当根节点是…

树莓派4B(Raspberry Pi 4B)使用docker搭建nacos集群

树莓派4B&#xff08;Raspberry Pi 4B&#xff09;使用docker搭建nacos集群 由于国内访问不了docker hub&#xff0c;我选用的国内适配树莓派ARM架构的nacos镜像——centralx/nacos-server。本文涉及到docker compose和docker network方面的知识&#xff0c;基于nacos 2.0.4&am…

《区块链公链数据分析简易速速上手小册》第4章:交易数据分析(2024 最新版)

文章目录 4.1 解析交易输入和输出4.1.1 基础知识4.1.2 重点案例&#xff1a;追踪比特币交易4.1.3 拓展案例 1&#xff1a;以太坊交易的输入输出解析拓展案例1&#xff1a;以太坊交易的输入输出解析步骤1: 连接到以太坊网络步骤2: 获取交易数据步骤3: 解析交易输入结论 4.1.4 拓…

LLM大模型相关问题汇总---包括问题与答案

一、基础篇 1. 目前主流的开源模型体系有哪些&#xff1f; - Transformer体系&#xff1a;由Google提出的Transformer模型及其变体&#xff0c;如BERT、GPT等。 - PyTorch Lightning&#xff1a;一个基于PyTorch的轻量级深度学习框架&#xff0c;用于快速原型设计和实验…

Uipath 调用Python 脚本程序详解

Python 活动概述 UiPath.Python.Activities 是一个新的活动包&#xff0c;创建它是为了支持直接从工作流运行 Python 脚本和方法。 其包含以下活动&#xff1a; Python 作用域(Python Scope) - 为 Python 活动提供作用域的容器。 加载 Python 脚本(Load Python Script) - 将 P…

A股上市以来涨幅排行榜

一、统计数据说明 1. 涨幅排行榜是根据股价的后复权价格计算的&#xff0c;该价格考虑了分红送股拆股等事件对股价的影响&#xff0c;相当于是分红再投资的股价。 2. 年化投资收益率&#xff0c;是根据IPO收盘价至今涨幅计算的复合年化收益率。例如&#xff0c;假设一个股票上…

中国电子学会2023年12月份青少年软件编程Scratch图形化等级考试试卷四级真题(含答案)

2023-12 Scratch四级真题 分数&#xff1a;100 题数&#xff1a;24 分数&#xff1a;60min 一、单选题(共10题&#xff0c;共30分) 1.运行下列程序&#xff0c;输入“abcdef”&#xff0c;程序结束后&#xff0c;变量“字符串”是&#xff1f;&#xff08;B&#xff09;(3…