数据结构——包装类&&泛型

一:包装类

在Java中,由于基本类型不是继承⾃Object,为了在泛型代码中可以⽀持基本类型,Java给每个基本类型都对应了⼀个包装类型。

类型、基础数据类型(内置数据类型):byte int short long float double boolean char 、

引用类型:所有的类(引用类型)都是直接间接继承Object类。

java是希望把所有的类型统一达成Object体系

包装类:标准库中创建了一组类,把内置类型的变量,包一下。

1.1:基本数据类型和对应的包装类

除了 Integer 和 Character, 其余基本类型的包装类都是⾸字⺟⼤写。

1.2:装箱和拆箱

虽然包装类,确实是类,在使用的时候,进行算术运算,还是需要转成内置类型,在进行运算。

包装类和内置类型转换。

内置类型-》包装类:装箱

包装类-》内置类型:拆箱

java 复制代码
int i = 10;
 // 装箱操作,新建⼀个 Integer 类型对象,将 i 的值放⼊对象的某个属性中
 Integer ii = Integer.valueOf(i);
 Integer ij = new Integer(i);

 // 拆箱操作,将 Integer 对象中的值取出,放到⼀个基本数据类型中
 int j = ii.intValue();

这个我们了解一下就可以了,现在的从ava8开始,已经可以自动拆箱装箱了。

1.3:自动拆箱和装箱

java 复制代码
public class Test {  
    public static void main(String[] args) {  
        //内置类型,赋值给包装类  
       // Integer i = 10;  
        //包装类,赋值给内置类型、自动拆箱  
       // int n=i;  
  
        Integer i = 10;  
        Integer j = 20;  
        System.out.println(i+j);//这里的+就是针对两个Integer先转int在计算

对于包装类来说,拿过来直接用进行了,当内置类型来用。

但有的地方需要使用包装类,不能使用内置类型。

java 复制代码
面试题:
下列代码输出什么,为什么?
Integer a = 127;  
Integer b = 127;  
Integer c = 128;  
Integer d = 128;  
System.out.println(a == b);  
System.out.println(c == d);
//true
//false

jvm针对Integrt这样的常量也做了优化

-128->127这个范围的数字,Integrt对象提前创建好了,保存到了一个"常量池"中。

jvm缓存了哪些integer对象,取决于jvm的实现。

二:范型

2.1:什么是泛型

⼀般的类和⽅法,只能使⽤具体的类型: 要么是基本类型,要么是⾃定义的类。如果要编写可以应⽤于多种类型的代码,这种刻板的限制对代码的束缚就会很⼤。----- 来源《Java编程思想》对泛型的介绍。

泛型是在JDK1.5引⼊的新的语法,通俗讲,泛型:就是适⽤于许多许多类型。从代码上讲,就是对类型实现了参数化。

2.2:引出泛型

泛型就是把所有程序员所需要的类型都包含上。

  1. 我们以前学过的数组,只能存放指定类型的元素,例如:int[] array = new int[10]; String[] strs =new String[10];

  2. 所有类的⽗类,默认为Object类。数组是否可以创建为Object?

java 复制代码
class MyArray {

public Object[] array = new Object[10];

public Object getPos(int pos) {

return this.array[pos];

}

public void setVal(int pos,Object val) {

this.array[pos] = val;

}

}

public class TestDemo {

public static void main(String[] args) {

MyArray myArray = new MyArray();

myArray.setVal(0,10);

myArray.setVal(1,"hello");//字符串也可以存放

String ret = myArray.getPos(1);//编译报错

System.out.println(ret);

}

}

问题:以上代码实现后 发现

  1. 任何类型数据都可以存放

  2. 1号下标本⾝就是字符串,但是确编译报错。必须进⾏强制类型转换

虽然在这种情况下,当前数组任何数据都可以存放,但是,更多情况下,我们还是希望他只能够持有⼀种数据类型。⽽不是同时持有这么多类型。所以,泛型的主要⽬的:就是指定当前的容器,要持有什么类型的对象。让编译器去做检查。此时,就需要把类型,作为参数传递。需要什么类型,就传⼊什么类型。

三:语法

基础语法

java 复制代码
class 泛型类名称<类型形参列表> {
// 这⾥可以使⽤类型参数
}
class ClassName<T1, T2, ..., Tn> {
}

其他写法:

java 复制代码
class 泛型类名称<类型形参列表> extends 继承类/* 这⾥可以使⽤类型参数 */ {
// 这⾥可以使⽤类型参数
}
class ClassName<T1, T2, ..., Tn> extends ParentClass<T1> {
// 可以只使⽤部分类型参数
}

四:泛型的使用

java 复制代码
package object.package1;  
class MyArrayTemplate<T> {  
    //此时arr是T[]类型 T是啥类型? 还不知道,得在后面实例化的时候才知道  
    //由于T类型位置,不能直接new T[]  
    private T[] arr=(T[]) new Object[10];  
  
    public T get (int index){  
        return arr[index];  
    }  
    public void set (int index, T value){  
        arr[index]=value;  
    }  
  
}  
  
public class Test3 {  
    public static void main(String[] args) {  
        //针对MyArrayTemplate的进行实例化  
        //泛型参数类型T是Integer  
        //针对arr来说,就只能存储Integer类型  
        MyArrayTemplate<Integer> myArray = new MyArrayTemplate<Integer>();  
        myArray.set(0, 10);  
        System.out.println(myArray.get(0));  
  
        //针对MyArrayTemplate的进行实例化  
        //泛型参数类型T是String  
        MyArrayTemplate<String> myArray2 = new MyArrayTemplate<String>();  
        myArray2.set(0, "hello");  
        System.out.println(myArray2.get(0));  
    }  
}
//10
//hello

针对泛型参数来说,只能指定引用类型,不能指定内置类型(int 就不可以。)

泛型这一套语法体系,底层还是靠Object这一些列的继承来完成的。

了解: 【规范】类型形参⼀般使⽤⼀个⼤写字⺟表⽰,常⽤的名称有:

E 表⽰ Element

K 表⽰ Key

V 表⽰ Value

N 表⽰ Number

T 表⽰ Type

S, U, V 等等 - 第⼆、第三、第四个类型

java 复制代码
也可以省略实例化的一部分:(类型推导)
MyArrayTemplate<Integer> myArray = new MyArrayTemplate<Integer>();  
转换为:
MyArrayTemplate<Integer> myArray = new MyArrayTemplate<>();  

五:裸类型

5.1: 说明

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

MyArray list = new MyArray();

只是警告但不报错,

注意: 我们不要⾃⼰去使⽤裸类型,裸类型是为了兼容⽼版本的 API 保留的机制

下⾯的类型擦除部分,我们也会讲到编译器是如何使⽤裸类型的。

⼩结:

  1. 泛型是将数据类型参数化,进⾏传递

  2. 使⽤ <T> 表⽰当前类是⼀个泛型类。

  3. 泛型⽬前为⽌的优点:数据类型参数化,编译时⾃动进⾏类型检查和转换

六:泛型如何编译的

6.1 :擦除机制

那么,泛型到底是怎么编译的?

  1. 基本概念:

在编译时,Java 编译器会将泛型类型信息从代码中移除,这个过程就叫做类型擦除。

擦除后,泛型类型会被替换为其边界类型(通常是 Object)或者指定的类型。

  1. 擦除过程:

将泛型参数替换为其边界或 Object。

在必要的地⽅插⼊类型转换以保持类型安全。

⽣成桥接⽅法以保持多态性。

七 :泛型的上界

针对某个类泛型参数,能填啥,做出限制。

上界:约定了泛型参数的父类,然后有一个界限。

例如:泛型参数只能填数字不能填字符串

或者泛型参数只能填Animal,就是有限制。

7.1:语法

java 复制代码
class 泛型类名称<类型形参 extends 类型边界> {
...
}

7.2:实例

java 复制代码
public class Test4 <T extends Number> {  
    
}
继承Number父类,它的子类只能是数字
Test4<Integer> l1; // 正常,因为 Integer 是 Number 的⼦类型

Test4<String> l2;//// 编译错误,因为 String 不是 Number 的⼦类型
这样就不可以使用,
eg:
public class Test4 <T extends Number> {  
    public static void main(String[] args) {  
  
        Test4<Integer> t1 = new Test4<Integer>();  
        Test4<Double> t2 = new Test4<Double>();  
        Test4<Float> t3 = new Test4<Float>();  
        Test4<Long> t4 = new Test4<Long>();  
        Test4<Short> t5 = new Test4<Short>();  
        Test4<Byte> t6 = new Test4<Byte>();  
  
        Test4<String> t7 = new Test4<String>();//String表示Number子类

也就是继承,然后类型匹配,不能匹配就不执行。

八:通配符(统统匹配)

java 复制代码
public class Test5 <T>{  
    public static void main(String[] args) {  
        Test5<Integer> t1 = new Test5<Integer>();  
        //报红就不能实例化,因为泛型参数不匹配  
        t1= new Test5<String>();  
        //这个情况就是不挑食,无论泛型参数是什么,都可以通过t来实例化  
        //此处?就是通配符  
        Test5<?> t= new Test5<Integer>();  
        t= new Test5<String>(); 

在"?"的基础上⼜产⽣了两个⼦通配符:

? extends 类:设置通配符上限:

java 复制代码
//指定了通配符的上界  
//此时t1可以实例化Integer,String,Double等所有Number的子类  
Test5<? extends Number> t1= new Test5<Integer>();  

//错误写法,String类型不是Number的子类,所以编译报错  
t1 = new Test5<String>();

? super 类:设置通配符下限(都是一样的规则,也就是不能超过子类)

九:总结

本片博客讲述了包装类和泛型,为接下来进入数据结构,开启新篇章。

大家也要了解以下几个问题:

包装类:

1包装类是什么

2包装类和内置类型的对应关系

3包装类和内置类型的转换(装箱拆箱)

泛型:

1:泛型解决了什么

2:泛型类咋怎么定义

3:泛型类怎么实例化

相关推荐
江拥羡橙2 小时前
JavaScript异步编程:告别回调地狱,拥抱Promise async/await
开发语言·javascript·ecmascript·promise·async/await
轩情吖2 小时前
Qt常用控件之QComboBox
开发语言·c++·qt·控件·下拉框·qcombobox·桌面级开发
我不是混子2 小时前
Spring Boot启动时的小助手:ApplicationRunner和CommandLineRunner
java·后端
studyForMokey2 小时前
【Kotlin进阶】泛型的高级特性
android·开发语言·kotlin
gsfl2 小时前
redis常见数据结构及其编码方式
数据结构·redis
惜鸟2 小时前
Java异常处理设计
java
渣哥2 小时前
从 IOC 到多线程:Spring 单例 Bean 的并发安全性全解析
java
ajassi20003 小时前
开源 C# 快速开发(八)通讯--Tcp服务器端
开发语言·开源·c#
慕木沐3 小时前
SpringAI工具调用原理解析
java·spring ai