【数据结构】:不了解包装类和泛型的话,看这篇准没错

包装类

基本类型对应的包装类

Java是一个面向对象的编程语言,但其基本数据类型(如int、char、boolean等)并不直接支持面向对象的特性。为了弥补这一不足,Java为每种基本数据类型设计了一个对应的类,这些类统称为包装类(Wrapper Class)。包装类均位于java.lang包中。


装箱和拆箱

装箱(Boxing)和拆箱(Unboxing)是Java语言中关于基本数据类型(primitive types)和它们对应的包装类(wrapper classes)之间转换的两个重要概念。


装箱

  • 装箱是指将基本数据类型 转换为对应的包装类对象的过程。
  • 例如,将 int 类型转换为 Integer 类型。
java 复制代码
int a = 10;

Integer ii = Integer.valueOf(a);  //显示装箱 or 手动装箱
Integer jj = a;   //隐式装箱 or 自动装箱

我们查看这段代码的汇编代码 可以发现,两种装箱底层都是调用的 valueOf() 方法


拆箱

  • 拆箱是指将包装类对象 转换为对应的基本数据类型的过程。
  • 例如,将 Integer 类型转换为 int 类型。
java 复制代码
Integer ii = 10;

int a = ii;   //自动拆箱
int b = ii.intValue(a); //手动拆箱

我们查看这段代码的汇编代码 可以发现,两种拆箱底层都是调用的 intValue() 方法


阿里笔试题【Integer的比较】

java 复制代码
//判断两次输出分别是什么
Integer a = 100;
Integer b = 100;
System.out.println(a==b);

Integer c = 200;
Integer d = 200;
System.out.println(c==d)

答案:true false

解析:

  • 这些赋值的过程都是在进行装箱 ,所以都调用了 valueOf() 方法
  • if 判断条件可知,i 如果是在 [-128, 127] 之间,就是返回一个数组的值
  • 相反,若不在这个范围,就会随机实例化一个对象进行返回

  • 看题可知,100在范围之内,所以 a 和 b 都是返回 IntegerCache.cache[100-(-128)] = IntegerCache.cache[228],故 a == btrue
  • 而200不在范围内,所以 c 和 d 均随机实例化两个不同的对象,会占用内存中不同的位置,一定不会相等,故 c == dfalse

泛型

  • 属于一个语法
  • 简单来说就是适用于许多类型
  • 主要功能是把类型参数化 ,意味着可以传指定的类型参数

为什么要有泛型

举例:

  • 实现一个类,类中包含一个数组成员,使得数组中可以存放任何类型的数据,也可以根据成员方法返回数组中控某个下标的值

  1. 实现这个类,我们先定义一个 Object[] 数组,Object 使得这个数组可以放下任何类型的数据
  2. 然后创建一个 setArray(int pos, Object obj) 方法,用来在第 pos 位上存放数据 obj
  3. 再创建一个 Object getArray(int pos) 方法,用来返回第 pos 位的值
  4. 可是在当你在 pos = 1 的地方,传入一个 obj = 10 之后,当准备创建一个 int a 来接收 array[1] 这个值的时候,程序确保错了
  • 这是由于 getArray() 方法为了可以让数组能返回任意类型的数据,返回类型设置成了 Object
  • 而在要以 int 类型取出这个数据的时候,由于类型不匹配,导致报错
  • 若要成功接收,就需要强制类型转换,将 Object 的类型转化为 int

  • 因为这样操作下来非常麻烦,所以泛型就出现了

  • 上面例子的代码为:
java 复制代码
public class MyArray {  
    public Object[] array = new Object[10];  
  
    public void setArray(int pos, Object obj) {  
        array[pos] = obj;  
    }  
    public Object getArray(int pos) {  
        return array[pos];  
    }  
    public static void main(String[] args) {  
        MyArray myArray = new MyArray();  
        myArray.setArray(1,3);  
        int a = (int) myArray.getArray(1);  
    }
}

泛型语法

java 复制代码
class 泛型类名称<类型形参列表> {    // 这里可以使用类型参数

}

class ClassName<T1, T2, ..., Tn> { }
class 泛型类名称<类型形参列表> extends 继承类 { }

class ClassName<T1, T2, ..., Tn> extends ParentClass<T1> { }

  • 上面例子用泛型来写:
java 复制代码
public class MyArray<T> {  
    public Object[] array = new Object[10];  
  
    public void setArray(int pos, T obj) {  
        array[pos] = obj;  
    }  
    public T getArray(int pos) {  
        return (T) array[pos];  
    }  
    public static void main(String[] args) {  
        MyArray<Integer> myArray = new MyArray<>();  
        myArray.setArray(1,3);  
        Integer a = myArray.getArray(1);  
    }
}
  • 这里面存放数据的时候都是按照 T类型 来存放的,最后取出的时候是按照 Integer类型 来检查的,若索取出的值和实例化中 <> 内的类型一直,则可取出,反之报错

< >

  • 八种基本类型不能写在里面
  • 只能写包装类类型或者类类型,包装类可以,自己定义的类也可以

  • 小结:
    1. 泛型是讲数据类型参数化,进行传递
    2. 使用 表示当前类是一个泛型
    3. 泛型目前为止的优点:数据类型参数化、编译时自动进行类型检查和转换

泛型的上界

  • 在定义泛型类时,有时需要对传入的类型变量做一定的约束,可以通过类型边界来约束
  • 在泛型编程中,上界通过 extends 关键字(在Java中)来指定,用于声明一个类型参数必须是某个特定类或接口(或其子类/实现类)的实例。这允许在编译时进行更严格的类型检查,防止类型不匹配的错误

java 复制代码
public class MyArray<E extends Number> {   //只接受Number的子类型或Number本身作为E的类型实参
	... 
}


public class MyArray<E extends Comparable<E>> {  //E必须是实现了Comparable接口的
	... 
}

泛型方法

  • 泛型方法,顾名思义,就是在定义方法时引入了类型参数的方法。这些类型参数在调用方法时会被具体的类型所实例化,从而允许同一个方法接受不同类型的参数并返回相应类型的结果。泛型方法的类型参数通常放在方法返回类型之前,并使用尖括号 <> 包围。

java 复制代码
public <T extends Comparable<T>> T findMax(T[] array){  
    T max = array[0];  
    for(int i = 1; i < array.length; i++){  
        if(array[i].compareTo(max) > 0){  
            max = array[i];  
        }    
    }    
	return max;  
}
相关推荐
风象南2 分钟前
SpringBoot 控制器的动态注册与卸载
java·spring boot·后端
醇醛酸醚酮酯21 分钟前
Qt项目锻炼——TODO清单(二)
开发语言·数据库·qt
jioulongzi26 分钟前
记录一次莫名奇妙的跨域502(badgateway)错误
开发语言·python
我是一只代码狗29 分钟前
springboot中使用线程池
java·spring boot·后端
hello早上好42 分钟前
JDK 代理原理
java·spring boot·spring
PanZonghui1 小时前
Centos项目部署之Java安装与配置
java·linux
向阳@向远方1 小时前
第二章 简单程序设计
开发语言·c++·算法
沉着的码农1 小时前
【设计模式】基于责任链模式的参数校验
java·spring boot·分布式
Mr_Xuhhh1 小时前
信号与槽的总结
java·开发语言·数据库·c++·qt·系统架构
纳兰青华2 小时前
bean注入的过程中,Property of ‘java.util.ArrayList‘ type cannot be injected by ‘List‘
java·开发语言·spring·list