泛型的基础 装箱拆箱

举报
游离 发表于 2023/02/27 20:55:03 2023/02/27
【摘要】 泛型简单介绍@[toc]泛型可以放任何类型的数据,但是只能存放一种数据泛型的目的:制定当前的容器,需要什么类型的对象,让编译器去检查这个数据类型 泛型的举例//这里的T是一个占位符,代表当前类是泛型类class myArray <T>{ public T[] arr = (T[])new Object[10]; public T getPos(int pos) { ...

泛型简单介绍

@[toc]
泛型可以放任何类型的数据,但是只能存放一种数据

泛型的目的:制定当前的容器,需要什么类型的对象,让编译器去检查这个数据类型

泛型的举例

//这里的T是一个占位符,代表当前类是泛型类
class myArray <T>{
    public T[] arr = (T[])new Object[10];

    public T getPos(int pos) {
        return arr[pos];
    }

    public void setVal(int pos, T val) {
        this.arr[pos] = val;
    }
}


public class test {
    public static void main(String[] args) {
        //往泛型里面放String
        myArray <String> myArray = new myArray<String>();//泛型就是将数据类型作为参数传进来,之后编译器就会去检查这个类型
        myArray.setVal(1, "hehe");
        String s = myArray.getPos(1);
        System.out.println(s);

        //往泛型里面放int类型
        myArray<Integer> myArray1=new myArray<Integer>();
        myArray1.setVal(2, 23);
        int a = myArray1.getPos(2);
        System.out.println(a);
    }
}

注意点

1、<包装类>就指定了数据类型,说明这个类里面只能放这个数据类型的数据,<>代表一个占位符,表示当前是一个泛型类

2、在new泛型的时候,第二个<>里面的类型可以不写,编译器会自己推导出来的

泛型的编译机制

泛型的编译原理就是:擦除机制

可以在 IDEA里面安装插件(jcalsslib Bytecode viewer)查看泛型的方法的字节码知道,首先要先build一下project来生成最新的 字节码文件

擦除机制 : 在编译过程中,将所有的T都替换成Object的机制

擦除机制是在编译时期的一种机制,在运行的时候,已经没有泛型这个概念了

//写一个泛型类,求出一个数组的最大值
//不要擦除成Object,由于不知道这个数组是什么类型的,所以要使用比较器,只要在T后面实现这个接口就行
 class  Alg<T extends Comparable<T>>{  //T 实现了 Comparable接口

    public T findMxaVal(T[] array) {   //返回值是T,这是一个泛型方法
        T maxVal = array[0];
        for (int i = 1; i < array.length; i++) {
            if (array[i].compareTo(maxVal) > 0) {
                maxVal = array[i];
            }
        }
        return maxVal;
    }

}
public class TestDemo2 {
    public static void main(String[] args) {
        Alg<Integer> alg = new Alg<>();
        Integer[] array = {12, 34, 1};//这里是引用类型
        int val = alg.findMxaVal(array);
        System.out.println(val);
    }
}

通配符?既有上界又有下界,而泛型只有上界

基本数据类型和包装类

基本数据类型 包装类
byte Byte
short Short
int Integer
long Long
float Float
double Double
char Character
boolean Boolean

int 的包装类 是Integer

char 的包装类是 Character

其余的基本数据类型都是首字母大写

装箱与拆箱

装箱和拆箱也叫做装包 拆包

装箱是指 将基本数据 类型变成包装类

拆箱是指 将包装类变成 基本数据类型

//装箱与拆箱
public static void main(String[] args) {
    	int a = 1;
        Integer A = a;//自动装箱---底层调用的还是Integer.valueOf
        Integer B = new Integer(a);//显式装箱
        Integer C = Integer.valueOf(a);//显式装箱
        System.out.println(A);
        System.out.println(B);
    	//打印的结果都是1
    
        int b = A;//自动拆箱-A的数据类型是Integer
        System.out.println(b);
        int c = A.intValue();//Integer-->int
        System.out.println(c);
        double d = A.doubleValue();//Integer-->double
        System.out.println(d);
}

一个例子

运行以下的代码:

public static void main(String[] args) {
    Integer a = 120;
    Integer b = 120;
    System.out.println(a == b);

    Integer c = 200;
    Integer d = 200;
    System.out.println(c == d);
}
//结果分别是true 和 false

为什么会发生上面的情况?

上面发生了自动装箱,而自动装箱底层调用的是Integer.valueOf

查看Integer.valueOf源码

public static Integer valueOf(int i) {
    if (i >= IntegerCache.low && i <= IntegerCache.high)//low 是-128 ,high是127
        return IntegerCache.cache[i + (-IntegerCache.low)];//所以数组的下标从0到255
    return new Integer(i);
}
//这段源码就是说,首先会对i进行判断,要是i是在-128 到 127 之间,就返回数组中的元素,否则就创建一个新的对象

image-20220911141645264

所以,上面的c和d取值是200,超过了127,就会分别创建对象,两个的哈希值不一样,所以打印结果是false

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。