Java详细分析讲解泛型
作者:星鸦wyk 发布时间:2023-02-05 07:56:02
1.泛型概念
泛型就是将类型参数化
所谓类型参数化就是将类型定义成参数的形式,然后在使用此类型的时候的时候再传入具体的类型
到这我们可以看出来:泛型在定义的时候是不知道具体类型的,需要在使用的时候传入具体的类型,泛型可以用在类、接口和方法中,这样做的好处是一个泛型可以适用多种情况
2.泛型的使用
2.1泛型类语法
public class 类名<T> {......}
<T>表示这是一个泛型类,T是type的首字母大写,除此之外的名称还有:
E:element
K:key
V:vlaue
N:number
<>中可以有多个类型参数,中间使用逗号隔开
2.2泛型方法语法
public<泛型类型> 返回值 方法名(泛型类型 参数) {......}
2.3泛型接口语法
public interface 接口名<泛型类型> {......}
2.4泛型在main方法中的使用
下面写一个泛型类来引出后面的内容
class Fc<T>{
private T a;
public T get (T data) {
this.a=data;
return a;
}
}
前面说过泛型是在使用的时候再传入具体的类型,所以在实例化上面泛型类的时候要指定类型。具体方式如下
类名<具体类型>变量名=new 类名<具体类型>();
注意:
等号右边<>中可以不写具体类型,编译器可以根据上下文推导出此处的类型
<>中只能写入类,所以如果是基本数据类型,就需要写入其对应的包装类,包装类除int是Integer,char包装类是Character外,其余均是首字母大写
Java中不能创建泛型数组,至于原因要从Java中泛型的机制说起
3.擦除机制
Java实现泛型是依靠这个擦除机制的,这个机制目前来讲过于复杂,只说结果
Java编译器在编译的时候会去掉类型参数,而对于泛型类型来说,如果指定上界会用上界类型进行替换,没有指定上界则会以Object来进行替换
所以在编译的时候泛型类型都被替换成了Object,编译后的class文件是不包含任何泛型信息的,即泛型信息不会进入到运行时阶段
但Java的数组需要进行运行期类型检查,而由于类型擦除,造成数组运行期类型检查不能正常进行,破坏了Java数组运行期类型检查的机制
4.泛型的上界
所谓泛型的上界就是对传入的类型变量进行约束,指定哪些类型可以传入,哪些不行,语法如下:
class 类名<类型参数extends类型边界> {......}
还是以上面的泛型类为例,现在改成如下情况:
class Fc<E extends Number >{
private E a;
public E get (E data) {
this.a=data;
return a;
}
}
那么此时Fc就只能传入Number或者其子类
5.通配符
通配符就是“?”在泛型中使用,它是用来解决泛型无法协变的问题,那什么是协变?
假设有两个类A和B,A继承B,那么泛型Fc<A>应该也是Fc<B>的子类,但泛型不支持这样的父子关系
基于上面的情况,所以需要使用通配符
直接写两个类,A继承B
class B {
}
class A extends B {
}
现在把<B>改成<?>
5.1通配符的上界
通配符也可以指定界限,语法和泛型的上界类似
<? extends 类型边界>
假设<? extends Number>,那么可以传入的是Number及其子类
但需要注意的是:通配符的上界只能用来读取数据,不能用来写入数据
因为我们只知道里面可以传入什么类型的数据,但具体是什么类型我们不知道,所以也就无法对数据进行修改,但是读取则可以直接用父类对象来进行接收读取出来的数据
5.2通配符的下界
下界使用的是super
<? super 类型边界>
<? super Integer>表示可以传入Integer或者其父类
通配符下界可以进行写入数据,但不能用来读取数据
原因也很简单,里面可以传的类都是Integer或者它的父类,写进去的数据可以进行转化,但读取数据用哪一个父类对象接收则不好确定了
6.包装类
由于Java中基本数据类型不是继承Object类,所以为了泛型能够支持基本数据类型,每一个基本数据类型都有各自的包装类
基本数据类型 | 包装类 |
byte | Byte |
short | Short |
int | Integer |
long | Long |
float | Float |
double | Double |
char | Character |
boolean | Boolean |
6.1装箱和拆箱
装箱就是把基本数据类型改为对应的包装类类型,拆箱就是和装箱相反的操作
Java中提供了自动装箱和拆箱机制,但还是先来看下手动装箱和拆箱的操作
//手动装箱
int i=10;
Integer j=Integer.valueOf(i); //第一种操作
Integer j=new Integer(i); //第二种操作
//手动拆箱
int a=j.intValue();
自动装箱和拆箱的话代码就要少的多
int i=10;
Integer j=i; //自动装箱
int a=j; //自动拆箱
关于int的包装类有一个比较有趣的地方,装箱使用了valueOf方法,其源码如下:
可以看到传给方法的参数首先是和IntegerCache进行比较,如果参数的值是在某个范围中,那么返回的是数组里面的元素,否则返回新的对象
那我们来看看这个IntegerCache
也就是说-128<=i<=127的时候返回的是类中的数组的元素,那么就会有一个情况如下:
原因和上面所讲一样
泛型结束,后面数据结构的时间复杂度和空间复杂度这两个概念就不写了,下一篇直接到顺序表
来源:https://blog.csdn.net/qq_52989768/article/details/124542438


猜你喜欢
- 分栏是报刊、书籍、杂志常用的排版样式,它不仅能方便阅读,同时也能增加页面的美观度。本文将介绍如何在Java应用程序中给Word文档添加多个栏
- forword跳转页面的三种方式:1.使用serlvet/** * 使用forward跳转,传递基本类型参数到页面  
- 前言我们都知道浮点型变量在进行计算的时候会出现丢失精度的问题。如下一段代码:System.out.println(0.05 + 0.01);
- 经过各种各样的整理,以及和热心网友讨论,终于整理出了九种android开发中最常见的问题和解决方案再次跟大家分享下!!有用的话请顶顶帖子,共
- 1、 WIFI网卡的状态WIFI网卡的状态信息都以整型变量的形式存放在 android.net.wifi.WifiManager 类中,有以
- 背景在很多场景下面我们需要在集合发生变化的时候能够通过一个事件对外进行通知,默认的List<T>并没有此类功能,所以对于这一类需
- 23种设计模式第七篇:java代理模式定义:为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个对象不适合或者不能直接引用另一个
- 对于触摸屏,其原生的消息无非按下、抬起、移动这几种,我们只需要简单重载onTouch或者设置触摸 * setOnTouchListener即
- 本文实例讲述了C#关闭指定名字进程的方法。分享给大家供大家参考。具体实现方法如下:public static void stopNamedP
- 一、RatingBar简单介绍RatingBar是基于SeekBar(拖动条)和ProgressBar(状态条)的扩展,用星形来显示等级评定
- 前言平时开发经常会用到List等集合操作,在这里做一个小结java集合Collectionjava里面集合分为两大类:List和Set,下面
- 本文主要从两个方面对Android Volley框架的使用方法进行讲解,具体内容如下一、网络请求1.get方式请求数据// 1 创建一个请求
- delegate double ProcessDelegate(double param1, double param2); &n
- 使用正则表达式进行替换:代码片段:String documentTxt = EntityUtils.toString(entity,&quo
- 最近工作需要,自定了一个颜色选择器,效果图如下:颜色种类是固定的,圆环上有个指示器,指示选中的颜色,这个定义起来应该是很简单了,直接上代码。
- 实现功能实现使用FTP上传、下载、重命名、刷新、删除功能开发环境开发工具: Visual Studio 2013.NET Framework
- 1. 概述在 Spring Security 5.2 中增强了 DSL 的功能:允许使用 Lambda 表达式来配置 HTTP securi
- 前言偶然逛国外博客,看到了一个介绍文字动画的库,进入 pub 一看,立马就爱上这个动画库了,几乎你能想到的文字动画效果它都有!现在正式给大家
- WPF在样式定义和UI动画上面相对于以前的技术有了不少的提升,下面给出WPF技术实现钟表的效果:1、Visual Studio新建一个WPF
- 前言最近一直被无尽的业务需求淹没,没时间喘息,终于接到一个能让我突破代码舒适区的活儿,解决它的过程非常曲折,一度让我怀疑人生,不过收获也很大