java模型给泛型_【一天一个基础系列】- java之泛型篇

java 5以后,java引入了“参数化类型”的概念,允许程序在创建集合时指定集合元素的类型

java 7之前,如果使用带泛型的接口、类定义变量,那么调用构造器创建对象时构造器的后面也必须带泛型

比如

//java 7之前

List list = new ArrayList();//后面的是必须带上的

//java 7之后,"菱形"语法

List list = new ArrayList<>();

注:java 9允许在使用匿名内部类时使用菱形语法

概念定义:允许在定义类、接口、方法时使用类型形参,这个类型形参将在声明变量、创建对象、调用方式动态地指定

我们来看一下定义泛型接口、类

/**

* 定义泛型接口,实质:允许在定义接口、类时什么类型形参,

* 类型形参在整个接口、类体内可当成类型使用,几乎所有可

* 使用普通类型的地方都可以使用这种类型形参

*/

public interface List {

void add(T x);

}

/**

* 定义

*

*

*/

@Data

public class Clazz {

private T a;

public Clazz(T a){

this.a = a;

}

}

//使用Clazz

pulic void method(){

Clazz clazz = new Clazz<>("");

}

从泛型类派生子类

当创建了带泛型声明的接口、父类之后,可以为该接口创建实现类,或从该父类派生子类,需要指出的是,当使用这些接口、父类时不能再包含泛型形参

//定义类Son类继承Parent类

public class Son extends Parenet{

}

//使用Parent类时为T形参传入String类型

public class Son extends Parent{

}

//使用Parent类时,没有为T形参传入实际的类型参数

public class Son extends Parent{

}

像这种使用Parent类时省略泛型的形式被称为原始类型(raw type)

如果从Parent类派生子类,则在Parent类中所有使用T类型的地方都将被替换成String类型

并不存在泛型类

List与List 创建出来的是同样class文件,它们在运行时总有同样的类,故在静态方法、静态初始化块或者静态变量的生命和初始化中不允许使用泛型形参

public class R{

//错误,不能在静态变量声明中使用泛型形参

static T info;

//错误,不能再静态方法声明中使用泛型形参

public void foo(T p){

}

}

类型通配符

定义:为了表示各种泛型List的父类,可以使用类型通配符,类型通配符是一个问号(?),将一个问号作为类型实参传给List集合,写作:List>(意思是元素类型未知的List)。这个问号(?)被称为通配符,它的元素类型可以匹配任何类型

类型通配符的上限

定义:当直接使用List>·这种形式时,即表明这个List集合可以是任何泛型List的父类。但还有一种特殊的情形,程序不希望这个List>`是任何泛型List的父类,只希望它代表某一类泛型List的父类

//定义上限为Parent类,表示泛型形参必须是Parent子类

List extends Parent>

协变:对于更广泛的泛型类来说,指定通配符上限就是为了支持类型型变。比如Foo是Bar的子类,这样A就相当于A extends Bar>的子类,可以将A赋值给A extends Bar>类型的变量,这种型变方式被称为协变

类型通配符的下限

定义:通配符的下限用 super类型>的方式来指定,通配符下限的作用与通配符上限的作用恰好相反

//定义下限为Parent类

List super Parent>

逆变:比如Foo是Bar的子类,当程序需要一个A super Foo>变量时,程序可以将A、A赋值给A super Foo>类型的变量,这种型变方式被称为逆变

对于逆变的泛型而言,它只能调用泛型类型作为参数的方法;而不能调用泛型类型作为返回值类型的方法。口诀是:逆变只进不出

泛型方法

定义:所谓泛型方法,就是在声明方法时定义一个或多个泛型形参,与类、接口中使用泛型参数不同的是,方法中的泛型参数无须显式传入实际类型参数修饰符返回值类型 方法名(形参列表){

//TODO

}

泛型方法和类型通配符的区别

使用通配符比使用泛型方法(在方法签名中显式声明泛型形参)更加清晰和准确

类型通配符既可以在方法签名中定义形参的类型,也可以用于定义变量的类型;但泛型方法中的泛型形参必须在对应方法中显式声明

大多数时候都可以使用泛型方法来代替类型通配符//使用类型通配符

public interface Collection{

void add(Collection> p);

void delete(Collection extends E> p)

}

//使用泛型方法

public interface Collection{

void add(Collection p);

void delete(Collection p)

}

也可以同时使用泛型方法和通配符public class Collections{

public static void copy(List dest,List extends T> src){}

}

“菱形”语法与泛型构造器

“菱形”语法前面已经提到,不再赘述,说一下啥是泛型构造器,其实就是java允许构造器签名中声明泛型形参class Foo{

public Foo(T t){

}

}

public void method(){

//泛型构造器中T类型为String

new Foo("");

//也可以这么定义,显示指定T类型为String

new Foo("");

//泛型构造器中T类型为Integer

new Foo(10);

}

泛型方法与方法重载

因为泛型既允许设定通配符的上限,也允许设定通配符的下限,从而允许在一个类里包含以下两种方法的定义 void copy(Collection des,Collection extends T> src){};

T copy(Collection super T> des,Collection src){};

重载的情况public void method(List list){}

public void method(List list){}

上述这段代码是不能被编译的,因为参数List和List编译之后都被擦除了, 变成了同一种的裸类型List,类型擦除导致这两个方法的特征签名变得一模一样(下面会提到类型擦除)

类型推断

java 8改进了泛型方法的类型推断能力,类型推断主要有如下两方面

1)可通过调用方法的上下文来推断泛型的目标类型

2)可在方法调用链中,将推断得到的泛型传递到最后一个方法

泛型擦除和转换

擦除:当把一个具有泛型信息的对象赋给另一个没有泛型信息的变量时,所有在尖括号之间的类型信息都将被扔掉;Java代码编译成Class文件, 然后再用字节码反编译工具进行反编译后, 将会发现泛型都不见了, 程序又变回了Java泛型出现之前的写法, 泛型类型都变回了裸类型(List 对应的裸类型就是List)

比如:List 类型会被转换成List,则该List对集合元素的类型检查变成了泛型参数的上限(Object),那么在使用,比如插入的时候,又会出现从Object到String的强制转型代码

擦除法所谓的擦除, 仅仅是对方法的Code属性中的字节码进行擦除, 实际上元数据中还是保留了泛型信息, 这也是我们在编码时能通过反射手段取得参数化类型的根本依据

java不支持原生类型的泛型,即是不支持 int/long等,List这种是不支持的,那么一旦把泛型信息擦除后,遇到原生类型时把装箱、 拆箱也自动做了,这也成为Java泛型慢的重要原因

泛型与数组

数组元素的类型不能包含泛型变量或泛型形参,除非是无上限的类型通配符,但可以声明元素类型包含泛型变量或泛型形参的数组。也就是说,只能声明List[]形式的数组,但不能创建ArrayList[10]这样的数组对象

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

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

相关文章

mpython掌控板作品_第1课 Arduino micro:bit 掌控板 创客教育常用的3类主控板

有很多朋友想学习创客&#xff0c;问我怎么学习。我建议他先百度一下“创客”&#xff0c;看看有什么感觉。结果还是很懵&#xff0c;五花八门&#xff0c;什么都有&#xff0c;找不到核心。简单理解&#xff0c;就是以前讲的DIY&#xff0c;自己动手&#xff0c;制作一个东西。…

redis启动没反应_Promethues如何针对Redis进行监控

需求&#xff1a;采用redis_exporter 收集数据&#xff0c;promethus采集redis_exporter数据&#xff0c;granfana展示数据一、简易安装redisyum install -y redisrpm -qa |grep redislsof -i :6379rpm -ql redissystemctl start redis找到配置文件/etc/redis.conf,修改 requir…

网上书店管理系统java部分代码_网上书店管理系统 java语言

【实例简介】整个系统&#xff0c;包括数据库&#xff0c;安装上就能用&#xff0c;非常适合做课程设计的作业或者毕业设计的作业【实例截图】【核心代码】OnLineBookStore└── OnLineBookStore├── WebRoot│ ├── META-INF│ │ └── MANIFEST.MF│ ├── W…

java自定义标签遍历_自定义标签 - CarlDing的个人页面 - OSCHINA - 中文开源技术交流社区...

EL的不足&#xff0c;由JSTL来加强 -> 自定义标签来实现。1&#xff1a;自定义标签1&#xff1a;自定义标签也是类。2&#xff1a;让用户在JSP页面使用&#xff0c;不引用Java代码的情况下&#xff0c;调用Java代码。2&#xff1a;标签开的类的继承关系3&#xff1a;快速的…

python宏替换_简单的宏替换

简单的宏替换1.宏定义必须写在第一次使用该宏定义的代码之前&#xff1b;2.宏定义不是以分号结束的3.#define string1 string2 之间至少要有一个空格4.string 1称为宏&#xff0c;string2 称为宏扩展5. 宏名用大写的字母表示是一个习惯6.使用宏的好处&#xff1a;a 简化程序的书…

python逆序数怎么求_怎么算逆序数?急~~~!!!

展开全部可使用直bai接计数法&#xff0c;计算一个du排列的逆序数的直接zhi方法是逐个dao枚举逆序&#xff0c;同时统计个内数。举个例子&#xff1a;标准列是容1 2 3 4 5&#xff0c;那么 5 4 3 2 1 的逆序数算法&#xff1a;看第二个&#xff0c;4之前有一个5&#xff0c;在标…

java解析xml中文字符乱码_Eclipse读取xml中文乱码问题解决

【mysql】高可用集群之MMM一.复制的常用拓扑结构 复制的体系结构有以下一些基本原则: (1) 每个slave只能有一个master: (2) 每个slave只能有一个唯一的服务器ID: (3) 每个maste ...公钥私钥 ssl&sol;tsl的概念一,公钥私钥1,公钥和私钥成对出现2,公开的密钥叫公钥,…

springboot整合rocketmq_面试官:简单说一下RocketMQ整合SpringBoot吧

前言在使用SpringBoot的starter集成包时&#xff0c;要特别注意版本。因为SpringBoot集成RocketMQ的starter依赖是由Spring社区提供的&#xff0c;目前正在快速迭代的过程当中&#xff0c;不同版本之间的差距非常大&#xff0c;甚至基础的底层对象都会经常有改动。例如如果使用…

java面试常考_JAVA面试常考系列十

JAVA面试常考系列十题目一Servlet是什么&#xff1f;Servlet(Server Applet)是Java Servlet的简称&#xff0c;称为小服务程序或服务连接器&#xff0c;是用Java编写的服务器端程序&#xff0c;主要的作用是处理客户端请求并生成动态Web内容。一般情况下&#xff0c;Servlet主要…

的ui在vs中显示没有成员_在电脑桌面使用敬业签团队便签怎么设置新增内容在上面显示?...

实时跟进小组成员的各项任务的完成情况&#xff0c;及时将工作任务安排下去&#xff0c;是提高团队工作效率的较为有效的方法。在监督小组成员任务状况以及及时安排工作方面&#xff0c;选择一款支持多人同步在线协作的软件是非常有必要的。敬业签团队便签是一款不受系统、设备…

Java利用二维数组判断节假日_《剑指offer》面试题3 二维数组中的查找 Java版

(二维数组&#xff0c;每行递增&#xff0c;每列递增。输入二维数组和一个整数&#xff0c;判断数组中是否含有此数。)我的方法&#xff1a;拿到题目&#xff0c;根据题目条件我提取出这样一个特性&#xff1a;一个数的右边和下面的数都比它大。于是就可以写出一种递归的方法&a…

多表关联查询_【函数007】 EXCEL多表关联查询实战

继续函数实战系列教程&#xff0c;今天要分享的案例是根据填写的表名自动提取对应表中的数据数据准备&#xff1a;需求说明&#xff1a;我们希望实现&#xff0c;我们选择不同月份&#xff0c;显示对应月份表中的数据&#xff01;处理方案&#xff1a;1、构建下拉列表(菜单)数据…

java if emun_关于java:Enum与If-else

我有一个需求&#xff0c;其中我需要从事件列表中构建如下的雇员对象。 目前&#xff0c;我的代码如下所示&#xff0c;但是QE发表评论说可能使用枚举而不是多个。有人可以建议我如何用枚举实现这一点。Employee e new Employee();for(Event event:events){if("empid"…

管理动物园动物c++_《过山车大亨》开发商公开新作 建立自己的动物园

知名模拟经营游戏开发商Frontier Developments近日宣布&#xff0c;旗下游戏《动物园之星》(Planet Zoo)即将在不久后发售&#xff0c;登录Steam平台。本座是一款模拟经营游戏&#xff0c;玩家在游戏中将会从零开始&#xff0c;建立一个属于自己的动物园世界。游戏中有多种不同…

Java_数组练习答案_Java数组练习题带答案.doc

《Java数组练习题带答案.doc》由会员分享&#xff0c;可在线阅读&#xff0c;更多相关《Java数组练习题带答案.doc(11页珍藏版)》请在人人文库网上搜索。1、一 填空题1) 数组的元素通过 下标 来访问&#xff0c;数组Array的长度为 Array.length 。2) 数组复制时&#xff0c;将一…

安费诺amphenol连接器_安费诺的Ellison谈信号完整性职业和他的免费开源PCB设计软??件...

Amphenol的信号完整性工程师杰森埃里森(Jason Ellison )Amphenol(安费诺) ICC的高级职员信号完整性工程师杰森埃里森(Jason Ellison )深入了解了网络&#xff0c;给予EE(电子)社区以及他的开源信号完整性项目的重要性。信号完整性工程与其他EE(电子)领域相比如何&#xff1f;他…

python形参和实参命名方式_Python的形参和实参使用方式

Python的形参和实参使用方式形参可以设置参数默认值&#xff0c;设置遵循从右至左原则例如&#xff1a;fun(x0,y1),fun(x,y1)&#xff0c;但不可以是fun(x1,y)形参设置可以为数字字符串变量、元组和字典等任意类型数据&#xff0c;元组形参是在变量名前加*&#xff0c;字典形参…

mysql的contains_mysql中json_contains、json_extract等json查询方法的使用

新版 Mysql 中加入了对 JSON Document 的支持&#xff0c;可以创建 JSON 类型的字段&#xff0c;并有一套函数支持对JSON的查询、修改等操作。JSON是一种轻量级的数据交换格式&#xff0c;采用了独立于语言的文本格式&#xff0c;类似XML&#xff0c;但是比XML简单&#xff0c;…

260多媒体语言如何调节_260马力配9.7米货厢,实拍柳汽H5小三轴载货车

【卡车之家 原创】高速公路按轴的收费实施让9米6大单桥载货车火了起来&#xff0c;能够满足快递快运、电商物流等以方量为主的轻型货物运输。但这种大单桥18吨的限重对于不少卡友来说或许不太够用&#xff0c;而8x4载货车又有些大材小用了。这时&#xff0c;处于中间位置的三轴…

php mysql复杂查询_半复杂的PHP / MySQL Select语句

我目前有3张桌子,我正在用这些桌子来预定某些设备.这是我的桌子&#xff1a;tblEquipment:id name description1 Camera Takes pictures2 Projector Projects pictures3 Laptop Portable ComputertblEvents:id start end first_name last_name email1 2009-08-10 2009-08-11 Jo…