什么是自动装箱拆箱_样品箱图片「建议收藏」

什么是自动装箱拆箱_样品箱图片「建议收藏」看了不少关于数据类型的文章(面向百度编程的时候),发现都没有跟装箱/拆箱联系起来,更没有讲解在实战中这些概念的运用以及为什么要这么运用,所以我把脑海里关于这些概念结合一些资料的补充把它们串联起来,通过下面的讲解后你会对

看了不少关于数据类型的文章(面向百度编程的时候),发现都没有跟装箱/拆箱联系起来,更没有讲解在实战中这些概念的运用以及为什么要这么运用,所以我把脑海里关于这些概念结合一些资料的补充把它们串联起来,通过下面的讲解后你会对java的数据类型以及实际运用有更深刻的了解,为的就是在平时码代码或者学习其他知识时能更通透。

开胃小菜

在讲解这一篇之前,先上一张java的数据分类图:
image.png
还有一张基本数据类型占用的空间和取值范围的表格,心里大概有个数,不用死记硬背:

数据类型 占用空间 取值范围 备注
byte 1字节 -2的31次方到2的31次方-1
boolean 1字节 false/true
char 2字节 0到2的16次方-1 java规定字符采用unicode编码,规定2个字节表示一个字符:char c = ‘s’
short 2字节 -32768~32767
int 4字节 -2的63次方到2的63次方-1
float 4字节 -2的149次方到2的128次方-1 带后缀F的浮点数值
long 8字节 -2的63次方到2的63次方-1
double 8字节 -2的1074次方到2的1024次方-1 不带后缀F的浮点数值

包装类和基本数据类型的区别

这一块有很多人都有点懵的知识点:

  • int和Integer的区别
  • double和Double的区别
  • float和Float的区别

… …
前者在上图可以看到都属于基本数值类型,后者在java中则被称为包装类Wrapper Class
我们拿Integer来解释下,先进入Integer的源码中看一眼:
image.png
继承了Number并实现了 Comarable 接口(接口里只有一个 compareTo 方法),定义了最大值最小值的范围(80000000~7fffffff),0x代表十六进制,略过…挑一个跟我们问题相关的代码:
image.png
Integer内部定义了一个int值 value (注意,有一个 final 修饰词,代表一旦创建了Integer对象,那么该对象就不会变了),有参构造器支持传入int值为 value 赋值,相当于是在为包装类Integer赋值,好,再往下看
image.png
是不是又发现了一个有参构造器,不同之处是传入了String类型(不要把String类型和上面的数据类型混为一谈,它比较特殊,后面会详细讲到),最终结果也是通过Integer的 parseInt() 方法给 value 赋值

上面这两种赋值行为我们称之为自动装箱,反之就是自动拆箱

Integer i = new Integer(666);//自动装箱
int ii = i.intValue();//自动拆箱

问题来了,这种装箱拆箱有什么意义吗,基本数据类型不能直接用吗?
先讲下这两者之间的主要区别:

  • 包装类是class,生成的对象是引用类型,对象是放在内存堆中的,通过引用来调用值,基本数据类型是把值放在栈内,也不需要引用,直接赋值(高效)
  • 包装类的初始值都是null,而基本类型都各不相同,比如int的初始值为0,boolean为false,且必须要先声明,否则编译期就会报错

image.png
总而言之,包装类是一种类,JDK提供的,不属于上述基本数据类型里的任何一种,是属于引用类型的类class

一个是引用类型的类,一个是基本数值类型,你觉得在java程序里用哪个操作数值转换会更方便点?
答案肯定是引用类型啦?

包装类的第一个好处:jdk提供了大量的方法供包装类来进行花式数值转换

比如把一个int=100的值按照8进制输出,可以这么做

int i = Integer.parseInt("100",8);//返回64

也有这样直接转成其他数值类型的,不必担心强转出错的问题
image.png

包装类的第二个好处:实体类创建用包装类的话程序对于非空判断比较好控制

比如创建一个实体类:

public class Student { 
   
    
    //学员姓名
    private String name;

    //考试成绩
    private int score;

    public String getName() { 
   
        return name;
    }

    public void setName(String name) { 
   
        this.name = name;
    }

    public int getScore() { 
   
        return score;
    }

    public void setScore(int score) { 
   
        this.score = score;
    }
}

如果数据返回age是空,定义的age因为int类型默认值为0所以会返回0,但是你能说这个学生考试成绩是0分吗?严谨点来说应该是查不到这个学生的考试成绩,而上面说到包装类的初始值是null,所以这里如果用 private Integer score; 作为成绩字段会更合适点(如果考试成绩是0那么Integer的值也是0,无就是返回null)
而且,在泛型和反射调用函数的时候也需要用到包装类

包装类的第三个好处:可以在一些collection/map中使用

image.png
用基本数值类型放在集合中时编译期间就会报错,包装类因为是class所以完全没问题,在实际应用肯定存在对数值进行集合操作的情况

好处这么多,那缺点肯定也有咯:

  • 装箱和拆箱会影响代码的执行效率
  • 在装/拆箱时可能会出现的各种异常

实际码代码的时候,基本数值类型和包装类型都会用到,但我觉得后者在实际开发的过程使用的情况多得多。

文章比较长,因为希望你们能理解(其实也有助于我能彻底搞懂),本篇文章的内容到这里就结束了,分割线下的是额外联想到的内容


特殊的String

你会发现,java代码里用的最多的String居然没有出现在上述的数据类型里,是不是很奇怪,那String到底算是什么类型?
String在java中被称为字符串,很明显,字符就是上面的字符类型char,那为什么平时编码一般都是使用String而很少使用char呢?
image.png
字符char只能占用两个字节,所以不能用char去定义多个字符(字符串),但可以用字符数组转成String字符串(早期的jdk确实会用char[]来作为字符串):

char[] cs = { 
   '第','一','次','操','作'};
System.out.println("输出结果:"+String.valueOf(cs));
System.out.println("字符串长度:"+String.valueOf(cs).length());

image.png

看到第一个应该是你们期待的结果,但是第二个字符串长度为什么是5而不是10?不是说一个字符占用两个字节吗?
答案:.length()方法输出的是字符个数,不是字节个数

转成字符串好麻烦,有么有更加简单的办法
当然有了! 如String cs = "第一次操作" ,因为太常用,所以为了简化操作jdk提供了这种语法,这种语法跟我们平常理解的字符串对象生成方式有区别,我们想的是生成一个String对象可以这样子嘛: String s = new String("啦啦啦") ,也可以,但是这样子做的坏处有两个:

  • 写法稍微麻烦了一点,相比前者
  • 直接在堆内存中创建新对象,不管是否已经存在相同值的对象

第一种创建对象的过程在下面会结合代码一起讲解,先看下String类里的源码。

和上面的包装类一样,会在String源码里发现这么一句话:
image.png
这个意味着什么?
字符串不可变,一旦生成字符串对象那么指向该字符串的对象不可再变,我们用下面的代码来验证这种说法:

String getfood = "我点了一只鸡翅";
String getfood2 = "我点了一只鸡翅";
System.out.println("两个字符串==结果:"+(getfood == getfood2));
System.out.println("两个字符串equals结果:"+(getfood.equals(getfood2)));

输出结果:image.png

为什么==的结果也是true,不是说是两个对象吗?其实是这样的,jdk在编译的时候会把字符串对象放到一个常量池里面(不管有多少个相同的字符串都会被当做一个对象),**这个常量池独立于栈和堆而存在,存储不可变量,**所以上面两个变量引用的都是同一个对象,那我们做一下改变,事先让两个字符串不同,在编译期后即放入常量池后再让两个字符串的值变一样:

String getfood = "我点了一只鸡翅";
String g1 = "我点了";
String g2 = "一只鸡翅";
String getfood2 = g1 + g2;
System.out.println("两个字符串==结果:"+(getfood == getfood2));
System.out.println("两个字符串equals结果:"+(getfood.equals(getfood2)));

输出结果:image.png

上面说到还有一种创建String对象的方式,我们来验证下这种方式的对象是否相等:

String s1 = new String("我点了一只鸡翅");
String s2 = new String("我点了一只鸡翅");
System.out.println("两个字符串==结果:"+(s1 == s2));
System.out.println("两个字符串equals结果:"+(s1.equals(s2)));

输出结果:image.png

所以说为什么我们平时都用string s1 = ““而不是用new string(””),不仅仅是因为方便,后者会每次在堆内存中创建一个新对象,而前者首先会在常量池里找有没有相同值的对象进行引用,有的话就直接引用不重新创建了。

总结下:String是jdk为了方便操作字符数组而创建的特殊类,可以与上述的包装类混为一谈,但不能与char像int与Integer之间的关系一样对应,需要懂得为什么平常都用String s1 = “”这种语法

这块内容可能还会有补充,先写到这吧…

今天的文章什么是自动装箱拆箱_样品箱图片「建议收藏」分享到此就结束了,感谢您的阅读。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/69100.html

(0)
编程小号编程小号

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注