【JavaSE】Java进阶知识一(泛型详解,包括泛型方法,协变,逆变,擦除机制)

目录

泛型

1. 什么是泛型

2.泛型方法

3.通配符上界(泛型的协变)

4.通配符下界(泛型的逆变)

5.泛型的编译(擦除机制)


泛型

        泛型:就是让一个类能适用于多个类型,就是在封装数据结构时能让封装的类型被各种类型使用所以引入了泛型的概念,虽然有了泛型,什么数据都可以放,但是更多情况下我们还是希望他只能持有一种数据类型。所以,泛型的主要目的:指定当前的容器,要持有什么类型的对象,让编译器去做检查。

1. 什么是泛型

语法格式如下:

泛型类<类型实参>变量名;//定义一个泛型类引用

new 泛型类<类型实参>(构造方法实参);//实例化一个泛型类对象

一般用<T>作为占位符 ,表示当前类是一个泛型类。Java中的泛型参数只能是引用类型,不能是基本类型,这与Java的泛型擦出机制有关。

 实例:

MyArray<Integer> list = new MyArray<Integer>();

*裸类型(Raw Type)      (这是一个泛型类但没有带着类型实参) 

MyArray list = new MyArray();

裸类型是为了兼容老版本的API保留机制,我们不要轻易使用。 

2.泛型方法

 泛型方法:定义一个泛型方法,我们需要在方法返回值前使用尖括号声明一个或多个泛型参数然在方法中就可以用到声明的泛型参数了,调用泛型方法时,我们不需要手动写出类型,编译器会根据你的调用,自动推导出具体类型。

静态泛型方法:泛型类有一个局限,静态方法和静态属性访问不了类上定义的泛型参数,静态泛型方法的定义和使用与普通泛型方法一致。

泛型类和泛型方法的使用场景:

当泛型参数需要在多个方法或成员属性间扭转,就使用泛型类,比如:集合。

当泛型参数只需要作用于某个方法,那就使用泛型方法。

3.通配符上界(泛型的协变)

泛型类型是具有不变性的,比如下面代码就是错误的:

Arraylist<Object> objectList;
ArrayList<String> stringList = new ArrayList<>();
objectList=stringList//这里会报错objectList.add(new Shit());
String str = stringList.get(0);
//因为我们无法将一个object对象转化为string对象,所以在编译层面上面的赋值就会直接报错

 为了让泛型变得更灵活,Java引入了通配符:?,通过下面的代码来给大家介绍一下通配符的作用:

在不使用通配符时,因为泛型的不变性,下面这段代码会出现问题,就使代码非常不灵活。

public static double sum(List<Number> list){double result =0;for(Number number : list){result += number.doubleValue();}return result;
}List<Double> doubleList = new ArrayList<>();
sum(doubleList)//这里会报错

我们可以使用通配符上界(?:extends T)来使代码更灵活

public static double sum(List<? extends Number> list){double result =0;for(Number number : list){result += number.doubleValue();}return result;
}List<Double> doubleList = new ArrayList<>();
sum(doubleList)

这种写法也被叫做泛型的协变 。

4.通配符下界(泛型的逆变)

我们还可以使用通配符下界(?:super T)来使代码变得灵活,代码实例如下:

class Food {
}
class Fruit extends Food {
}
class Apple extends Fruit {
}
class Plate<T> {
private T plate ;
public T getPlate() {
return plate;
}
public void setPlate(T plate) {
this.plate = plate;
}
}
public class TestDemo {
public static void main(String[] args) {
Plate<Fruit> plate1 = new Plate<>();
plate1.setPlate(new Fruit());
fun(plate1);
Plate<Food> plate2 = new Plate<>();
plate2.setPlate(new Food());
fun(plate2);
}
public static void fun(Plate<? super Fruit> temp){
// 此时可以修改!!添加的是Fruit 或者Fruit的子类
temp.setPlate(new Apple());//这个是Fruit的子类
temp.setPlate(new Fruit());//这个是Fruit的本身
//Fruit fruit = temp.getPlate(); 不能接收,这里无法确定是哪个父类
System.out.println(temp.getPlate());//只能直接输出
}
}

通配符的优缺点:

协变:放宽了对子类类型的泛型约束,但是缺点是不能对调用的参数进行写入数据只能进行读取数据。

逆变:放宽了对父类类型的泛型约束,但是缺点是不能对参数进行读取数据,只能写入数据。

5.泛型的编译(擦除机制)

擦除机制的实质就是,在编译阶段,Java的泛型类型可能是ArrayList<Integer>但是在java文件编译成字节码的过程中,泛型参数部分就被擦出了(泛型类,泛型方法的参数全部被替换成它的第一个上界或者顶级父类Object),在class文件中,无论参数是什么,JVM实际执行的代码类型其实是ArrayList<Object>类型,这也就引出了很多问题如下:

  1. 泛型参数只能是引用类型而不能是基本数据类型,因为基本数据类型无法被擦除成Object。
  2. 不能使用instanceof关键字进行泛型类型检测,因为在运行时所以的泛型类型都是裸类型。
  3. 泛型类型无法实例化类型参数T a=new T(),因为在运行时无法确定T的具体类型,也不知道T是否存在无参构造器。
  4. 无法实例化泛型数组T[] arry =new T[2];因为泛型最后都被擦除成Object数组,在使用时很容易发生类型转化异常,比如object转化不成string。

擦除机制是Java为了引入泛型这个语法而不得不做出的妥协之举,泛型语法是JDK5之后引入的,为了兼容老版本,不得不在编译阶段将泛型擦除成裸类型。但是在其他语言中,泛型的使用会非常自然且简单安全,在编写代码是我们要了解泛型擦除机制,否则可能会引发很多不必要的异常。

类型擦除是指在运行时对于JVM而言泛型参数被擦除掉了,并不代表泛型信息消失了,才class文件中泛型信息被以其他方式进行保存,我们依然可以在运行时通过反射的手段进行泛型类型检测。

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

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

相关文章

Python实验三:Python程序设计之组合数据类型

微信公众号&#xff1a;创享日记 发送&#xff1a;python实验 获取完整清晰报告和源码以及其它资源 前些天发现了一个巨牛的人工智能学习电子书&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;无广告&#xff0c;忍不住分享一下给大家。&#xff08;点击跳转人工智能学习…

Python爬虫和数据分析,石油原油加工产品产量数据处理分析

前些天发现了一个巨牛的人工智能学习电子书&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;无广告&#xff0c;忍不住分享一下给大家。&#xff08;点击跳转人工智能学习资料&#xff09; 微信公众号&#xff1a;创享日记 发送&#xff1a;原油分析 获取完整无水印报告P…

Python实验二:Python程序设计之结构与复用

微信公众号&#xff1a;创享日记 发送&#xff1a;python实验 获取完整清晰报告和源码以及其它资源 前些天发现了一个巨牛的人工智能学习电子书&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;无广告&#xff0c;忍不住分享一下给大家。&#xff08;点击跳转人工智能学习…

基于x86汇编的飞机大战

运行结果 代码 ;宏定义一个显示函数(显示一组字符串) PUTS MACRO STRINGPUSH AXPUSH DXLEA DX, STRING ;LEA将内存地址的

Python实验四:Python程序设计之文件

微信公众号&#xff1a;创享日记 发送&#xff1a;python实验 获取完整清晰报告和源码以及其它资源 前些天发现了一个巨牛的人工智能学习电子书&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;无广告&#xff0c;忍不住分享一下给大家。&#xff08;点击跳转人工智能学习…

【OFDM系列1】OFDM调制原理、参数、循环前缀、采样偏差、频偏及估计详解

关注公号【逆向通信猿】回复【OFDM】更精彩!!! OFDM调制解调原理 星座映射==>插入导频==>IFFT调制==>插入CP==>定时==>FFT解调==>导频均衡==>判决恢复 OFDM的正交条件[樊昌信,通信原理]: ①子载波 f k = k 2 T f_k=\frac{k}{2T}

Python统计英文单词出现情况次数实验

前些天发现了一个巨牛的人工智能学习电子书&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;无广告&#xff0c;忍不住分享一下给大家。&#xff08;点击跳转人工智能学习资料&#xff09; 一、题目 请统计附件hamlet.txt中出现的英文单词情况&#xff0c;统计并输出出现…

Java EE 8安全性API:概述

新的安全性API 可能&#xff0c;添加到Java EE 8中最重要的一项新功能就是新的安全性API。 此新API的主要动机是简化&#xff0c;标准化和现代化跨容器和实现处理安全性问题的方式。 他们做得很好。 由于三个新的注释使web.xml文件声明变得多余&#xff0c;Web身份验证的配置…

基于SSH的校园网上购物系统Javaweb、MySQL、JSP

微信公众号&#xff1a;创享日记 发送&#xff1a;校园购物 获取完整论文报告项目Java和SQL源码源文件答辩PPT等 主要内容&#xff1a; 1&#xff0e;对校园网上购物平台的建设需求进行分析&#xff0c;包括产品、服务方式等。 2&#xff0e;按需求对各个功能模块进行设计。 3&…

Python传感器采集数据文件分析处理实验源码

前些天发现了一个巨牛的人工智能学习电子书&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;无广告&#xff0c;忍不住分享一下给大家。&#xff08;点击跳转人工智能学习资料&#xff09; 一、题目 附件sensor-data.txt是一个传感器采集数据文件&#xff0c;其中&#…

Java Stream ORM现在带有JOIN

Speedment是一个Java Stream ORM工具包和运行时&#xff0c;它使您可以将数据库表作为标准Java Streams查看。 由于不必混合使用Java和SQL&#xff0c;因此该应用程序变得更加紧凑&#xff0c;从而使其开发速度更快&#xff0c;更不容易出错并且更易于维护。 流也严格地是类型安…

易购数码类电商商城网页设计与实现项目源码

前些天发现了一个巨牛的人工智能学习电子书&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;无广告&#xff0c;忍不住分享一下给大家。&#xff08;点击跳转人工智能学习资料&#xff09; 微信公众号&#xff1a;创享日记 发送&#xff1a;易购网站 获取完整报告论文源…

Python定义一个单链表可判断是否为空,计算长度,插入节结点实验

前些天发现了一个巨牛的人工智能学习电子书&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;无广告&#xff0c;忍不住分享一下给大家。&#xff08;点击跳转人工智能学习资料&#xff09; 一、题目 使用python定义一个单链表&#xff0c;并实现以下功能&#xff1a; (…

复信号两种不同加噪方式的比较

方式一 分别对信号实部和虚部加噪&#xff0c;SNR30&#xff0c;然后将实部和虚部合起来变成复信号&#xff0c;计算合起来之后的信号与噪声功率之比 %% 测试加噪方式 clear;close all;clc; M4;len10000; xk randi([0,M-1],1,len); xk pskmod(xk,4); SNR 30; xkR real(xk…

Python统计各省份字典中双一流学校数量实验

前些天发现了一个巨牛的人工智能学习电子书&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;无广告&#xff0c;忍不住分享一下给大家。&#xff08;点击跳转人工智能学习资料&#xff09; 一、题目 字典d中存储了我国42所双一流高校及所在省份的对应关系&#xff0c;请…

servlet文件上传下载_Servlet上传文件和下载文件示例

servlet文件上传下载Java Web应用程序中的文件上载和下载以及常见任务。 由于最近我写了很多有关Java servlet的文章 &#xff0c;因此我想提供一个使用servlet上传和下载文件的示例示例。 用例 我们的用例是提供一个简单HTML页面&#xff0c;客户端可以在其中选择要上传到服务…

Ollydbg使用教程学习总结(一)

解密系列之OD使用教程1 使用例子程序为Hello.exe OD基本快捷键及功能 从系统DLL领空返回到程序领空&#xff0c;AltF9 通过OD将程序的标题“Hello world”改为“OD Class 01” 直接单步执行法 按F8单步执行&#xff0c;找到MessageBox传参的地方&#xff0c;直接在数据窗口修…

Python连锁药店营业额数据分析实验

前些天发现了一个巨牛的人工智能学习电子书&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;无广告&#xff0c;忍不住分享一下给大家。&#xff08;点击跳转人工智能学习资料&#xff09; 一、题目 附件drug. order_ detai 1.xlsx是某连锁药店销售数据&#xff0c;请使…

Python计算细胞核与细胞质的面积比opencv或pil实验

前些天发现了一个巨牛的人工智能学习电子书&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;无广告&#xff0c;忍不住分享一下给大家。&#xff08;点击跳转人工智能学习资料&#xff09; 一、题目 根据附件cell.jipg&#xff0c;使用opencv库或者PIL库计算细胞核与细胞…

Ollydbg使用教程学习总结(二)

解密系列之OD使用教程4 程序1&#xff1a;RegisterMe.exe 把程序跑一遍之后我们发现程序有两个NAG&#xff0c;一个是在程序界面启动前出现&#xff0c;另一个是在程序关闭后出现的。 去掉第一个Nag方法如下&#xff1a; ①jmp跳过 ②全部nop掉 ③令hOwner参数为1&#xf…