包装类和泛型
创始人
2024-03-03 13:54:07

包装类和泛型严格来说算得上是JavaSE的内容,为什么他们要放在数据集合中?

这和集合类有关,我们在集合类中将会用到大量的泛型和包装类。

1. 包装类

基本介绍

包装类(wrapper)是针对八大基本数据类型相应的引用类型。

既然我们叫他包装类,那么类中肯定有方法:

例如:Integer

 那么包装类与基本数据类型的根本区别就在于能够调用方法,与此同时体现了面向对象。

我们先来看看吧大基本类型对应的包装类:

基本数据类型包装类
byteByte
shortShort
intInteger
longLong
floatFloat
doubleDouble
charCharacter
booleanBoolean

除了 Integer 和 Character, 其余基本类型的包装类都是首字母大写。

包装类和基本数据类型的转换

以int和Integer为例

1.jdk5前是手动装箱和拆箱的,装箱:基本类型 ——>包装类型。反之即为拆箱。

2.jdk5(含jdk5)是自动装箱和拆箱的。

3.自动装箱底层调用了valueOf方法。

public class demo {public static void main(String[] args) {int a = 10;Integer val =a;}
}

我们来看这段代码,它是如何进行自动拆箱和装箱的。

1. 先运行一遍程序,使之生成字节码文件

2.鼠标右键改Java文件,点击Explorer,如下图:

点击后: 

返回上一级目录,找到进入out目录下:

 再在目录表中输入cmd进入终端:

  3.进入终端后输入指令进入反汇编:javap -c demo(你的.Java文件名) 

 我们在反汇编中找到了valuOf()方法。

4. 在idea上选中Integer 按住ctrl + B 进入底层找到valuOf()方法

 传进来一个参数i ,返回时new 了一个Integer(i)。

 所以:

        int a = 10;//Integer val =a;//自动装箱Integer val = Integer.valueOf(a);//显示装箱Integer val2 = new Integer(a);//显示装箱

我们用这两种方法显示装箱。

我们来看看拆箱:

public static void main(String[] args) {Integer val =10;int a = val;System.out.println(a);}

 我们找到intValue :

2. 泛型(Generic)

泛型的引出

泛型的主要目的:就是指定当前的容器,要持有什么类型的对象。让编译器去做检查。此时,就需要把类型,作为参数传递。需要什么类型,就传入什么类型。

比如:在ArrayList(顺序链表下一章就会讲)中添加数据,我们利用之前学的去添加,并不能对添加的数据类型进行约束(不安全)。

例如:在ArrayList中添加多条狗,但是一不小心传递了一只猫,我们再对其进行遍历,调用foreach需要向下转型(转为Dog),这再运行就会报异常

不使用泛型的情况下:

使用泛型后: 

 它就自动检查想要添加进来的类型。

基本介绍

1. 泛型又称参数化类型,是jdk5.0以后出现的新特征,解决数据类型安全问题。

2. 再类声明或实例化时只要指定好需要的具体类型即可。

3.Java泛型可以保证如果程序在编译时没有发出警告,运行时就不会发生类型转换异常,同时代码更加健壮整洁。

4.泛型的作用是:可以在类声明是通过一个标识符表示某个属性的类型,或者某个方法的放回类型或者参数类型。

例如:

public class Main {public static void main(String[] args) {Person integerPerson = new Person<>(123);Person bit = new Person<>("bit");}
}class Person {E s ;//E表示S的数据类型,该数据类型在定义Person时指定,// 即在编译期间确定E是什么类型public Person(E s) {this.s = s;}public E f() {return s;}
}

语法声明

class 泛型类名称<类型形参列表> {
// 这里可以使用类型参数
}
class 类 {
}
class 泛型类名称<类型形参列表> extends 继承类/* 这里可以使用类型参数 */ {
// 这里可以使用类型参数
}
class 类 extends 类 {
// 可以只使用部分类型参数
}

interface 接口 {

说明:

1. K、T、V不代表值,而是表示类型

2. 可以使用任意字母表示:

E 表示 Element
K 表示 Key
V 表示 Value
N 表示 Number
T 表示 Type
S, U, V 等等 - 第二、第三、第四个类型

3.类名后的 代表占位符,表示当前类是一个泛型类

泛型的使用细节和注意事项

1.interface 接口 { } 和public class HashSet{ } 

T和E只能是同类型的引用

2. 在给泛型指定具体类型后,可以传入该类型或其子类型

例:若指定类型为A类,又需要添加B类,可以B类先继承A类再添加

3.泛型的使用形式

方法1:

ArrayList List = new ArrayList();

在实际应用中我们一般这么写:

ArrayList List = new ArrayList<>();

在我最开始学习面向对象的时候,看起来没有用到,其实默认是Object

Pig pig = new Pig();
//看起来啥都没有写,其实默认是
//因为Objec 默认是所有类型的父类
//这也就是个裸类型

裸类型(Raw Type)(了解)

说明:

裸类型是一个泛型类但没有带着类型实参,例如 MyArrayList 就是一个裸类型

MyArray list = new MyArray();

注意: 我们不要自己去使用裸类型,裸类型是为了兼容老版本的 API 保留的机制
下面的类型擦除部分,我们也会讲到编译器是如何使用裸类型的。

泛型的编译

那么,泛型到底是怎么编译的?这个问题,也是曾经的一个面试问题。泛型本质是一个非常难的语法,要理解好他还是需要一定的时间打磨。

代码:以泛型数组为例:

public class demo {public static void main(String[] args) {MyArray myArray = new MyArray();}
}
class MyArray {public E[] obj = (E[])new Object[3];public E[] getObj() {return obj;}public void setObj(E[] obj) {this.obj = obj;}}

我们进入终端,输入指令:javap -c  demo(.java文件名)

 简单讲解一下反汇编的代码:

 那么在程序编译好了以后跑进JVM,就没有了E[ ] 的概念了,我们泛型是在编译时期才存在的,一但程序运行起来以后,就不存在泛型这个概念了。E[ ] 在编译完成以后,就被擦除为了Object。

 泛型在编译期间只做两件事:

1. 存储数据时,帮我们进行自动类型检查

2. 获取元素时,帮我们完成自动类型转换

有关泛型擦除机制的文章截介绍:
Java泛型擦除机制之答疑解惑 - 知乎 (zhihu.com)

自定义泛型

介绍:

1. 一般由单个字母大写表示;

2. 可以有多个大写字母,如:

3. 普通成员也可以使用泛型

4. 使用泛型的数组不可以初始化(实例化),也就是不可以直接new;因为数组在new时无法确定T的类型,也就无法准确的开辟空间大小。

5. 静态的方法(属性)不可以使用泛型,在类加载时,自定义泛型还未创建(在创建对象时创建),所以JVM无法识别自定义泛型

自定义泛型接口

基本语法:

interface 接口名 { }

注意细节:

1. 接口中,静态成员也不可以使用泛型(原理如上);

2.泛型接口的类型在继承或者实现接口是确定

3. 如不指定则为默认的Object

自定义泛型方法:

例:

class Car {public  void fly(T t, R r) {//实现的代码}
}

泛型的继承和通配符说明 

1. 泛型不具备继承性

例如:

 MyArray myArray = new MyArray(); 

2. 如果需要对传入的类型变量做一定的约束,可以通过类型边界来约束;我们称之为泛型的上界
语法:

 class 泛型类名称<类型形参 extends 类型边界> {
...
}

还可以使用通配符,通配符类型(?)

例如:

//表示支持A类以及A的子类

?的默认是实现是,表示?是继承Object的任意类型。

3. 有泛型的上界,也就有泛型的下界:

例如:

// 表示支持A类以及A类的父类,并且不局限于A的直接父类

4. List<?>表示任意泛型类型均可接受

举个例子:

import java.util.ArrayList;
import java.util.List;public class demo {public static void printCollection1(List C) {for (Object object:C) {System.out.println(object);}}public static void printCollection2(List C) {for (Object object:C) {System.out.println(object);}}public static void printCollection3(List C) {for (Object object:C) {System.out.println(object);}}public static void main(String[] args) {ArrayList list1 = new ArrayList<>();ArrayList list2 = new ArrayList<>();ArrayList list3 = new ArrayList<>();ArrayList list4 = new ArrayList<>();}
}
class BB {}
class AA extends BB {}
 

我们的list1、list2、list3、list4均可以放入printCollection1()中;

我们的list3、list4均可以放入printCollection2()中;

我们的list1、list2均可以放入printCollection3()中;

相关内容

热门资讯

埃菲尔铁塔在哪 中国仿建埃菲尔... 2019年4月26日,广西南宁市,街头惊现一座巨型山寨版埃菲尔铁塔,高约20米,白色塔身,造型逼真,...
北京的名胜古迹 北京最著名的景... 北京从元代开始,逐渐走上帝国首都的道路,先是成为大辽朝五大首都之一的南京城,随着金灭辽,金代从海陵王...
苗族的传统节日 贵州苗族节日有... 【岜沙苗族芦笙节】岜沙,苗语叫“分送”,距从江县城7.5公里,是世界上最崇拜树木并以树为神的枪手部落...
长白山自助游攻略 吉林长白山游... 昨天介绍了西坡的景点详细请看链接:一个人的旅行,据说能看到长白山天池全凭运气,您的运气如何?今日介绍...
应用未安装解决办法 平板应用未... ---IT小技术,每天Get一个小技能!一、前言描述苹果IPad2居然不能安装怎么办?与此IPad不...
猫咪吃了塑料袋怎么办 猫咪误食... 你知道吗?塑料袋放久了会长猫哦!要说猫咪对塑料袋的喜爱程度完完全全可以媲美纸箱家里只要一有塑料袋的响...
脚上的穴位图 脚面经络图对应的... 人体穴位作用图解大全更清晰直观的标注了各个人体穴位的作用,包括头部穴位图、胸部穴位图、背部穴位图、胳...
世界上最漂亮的人 世界上最漂亮... 此前在某网上,选出了全球265万颜值姣好的女性。从这些数量庞大的女性群体中,人们投票选出了心目中最美...
demo什么意思 demo版本... 618快到了,各位的小金库大概也在准备开闸放水了吧。没有小金库的,也该向老婆撒娇卖萌服个软了,一切只...
埃菲尔铁塔在哪 中国仿建埃菲尔... 2019年4月26日,广西南宁市,街头惊现一座巨型山寨版埃菲尔铁塔,高约20米,白色塔身,造型逼真,...
苗族的传统节日 贵州苗族节日有... 【岜沙苗族芦笙节】岜沙,苗语叫“分送”,距从江县城7.5公里,是世界上最崇拜树木并以树为神的枪手部落...
北京的名胜古迹 北京最著名的景... 北京从元代开始,逐渐走上帝国首都的道路,先是成为大辽朝五大首都之一的南京城,随着金灭辽,金代从海陵王...
长白山自助游攻略 吉林长白山游... 昨天介绍了西坡的景点详细请看链接:一个人的旅行,据说能看到长白山天池全凭运气,您的运气如何?今日介绍...