java 自动装拆箱


title: “java 自动装拆箱”
tags:

  • Java

将基本数据类型封装成对象的过程叫做装箱(boxing),反之基本数据类型对应的包装类转换为基本数据类型的过程叫做拆箱(unboxing);

基本数据类型与其他对象的区别

基本数据类型

Java是一门面向对象的强类型语言,但它又不像python那样一切皆对象,Java中有一部分使用最频繁的数据结构并不是面向对象的,他们就是基本数据类型,也叫内置类型,他们在栈中储存,比起其他用new创建的对象,更加高效,Java有9中基本数据类型,分为五类

类型标识符备注
整型byte, short, int, long
浮点float, dauble
字符char
布尔boolean
void不能操作

基本数据类型的范围

整型的范围

  • byte: 占一个字节,也就是8位,最高一位作为符号位,有效位只有7位(采用补码存储)。
最大值:0,111 1111(127)
最小值:1,000 0000(-128)

怎么算的?
最高一位是符号位,这是固定的,正数用0表示,负数用1表示,然后后面的七位最大是7个1,最小是7个0,这就是用补码表示的byte能表示的最大最小数,把补码转换为原码(正数的补码就是源码,负数的补码变源码取反加一)然后转换为10进制。

  • short:占两个字节,16位,有效15位
最大值:2^15 -1: 32,767
最小值:-(2^15): -32,768
  • int: 占4个字节,最大值【2^31 - 1】(2,147,483,647), 最小值【-2^31】(-2,147,483,648)
  • long: 占8字节,最大值【2^63 - 1】(9,223,372,036,854,775,807),最小值【-2^63】(-9,223,372,036,854,775,808)

包装类型

Java中其他的对象都是继承自object的,有自己的属性和方法,为了方便基本基本数据类型和其他对象的的操作,Java为每个基本数据类型提供了对应的包装类型,

基本数据类型包装类
byteByte
booleanBoolean
shortShort
charCharacter
intInteger
longLong
floatFloat
doubleDouble
  • 为什么要使用包装类型

Java是一门面向对象的语言,大部分操作都是针对对象的,比如容器,容器中能存入的最大的范围就是object,而基本数据类型不属于对象,那他就无法存入容器,为了解决这个问题,必须把基本数据类型“包装”起来,让他作为一个对象参与到编程中。

装箱和拆箱

把基本数据类型包装成对象的过程叫做装箱,反之把对象转换为基本数据类型的过程叫做拆箱。
Java SE5 后,为了简化开发,提供了自动装拆箱机制,Java会在适当时刻自动转换基本数据类型和包装类型,如:

public class Demo1 {public static void main(String[] args) {Integer integer = 3; // 自动装箱int i = integer;  // 自动拆箱}
}

通过Javap反编译得到

  public static void main(java.lang.String[]);Code:0: iconst_31: invokestatic  #2                  // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;4: astore_15: aload_16: invokevirtual #3                  // Method java/lang/Integer.intValue:()I9: istore_210: return

在自动装箱时,其实是调用了包装类的valueOf()方法,而在自动拆箱时则调用了包装类的intValue()方法,所以如果在JavaSE5之前,没有自动装拆箱机制,上面的代码我们需要这样写

public class Demo1 {public static void main(String[] args) {Integer integer = Integer.valueOf(3); // 装箱int i = Integer.intValue(integer);  // 拆箱}
}

除int和Integer之外,其他基本类型和包装类的自动转换也一样,装箱时调用valueOf()方法,拆箱时调用xxxValue()方法。

什么时候自动装箱

1. 初始化,赋值,函数返回时

当把基本数据类型赋值给包装类时或者基本数据类型作为函数返回值但函数声明要求返回包装类型时,会自动装箱,如上面的例子

2. 将基本数据类型放入容器中

public void func2(){List<Integer> list = new ArrayList<>();list.add(1);}

反汇编之后

  public void func2();Code:0: new           #4                  // class java/util/ArrayList3: dup4: invokespecial #5                  // Method java/util/ArrayList."<init>":()V7: astore_18: aload_19: iconst_110: invokestatic  #2                  // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;13: invokeinterface #6,  2            // InterfaceMethod java/util/List.add:(Ljava/lang/Object;)Z18: pop19: return

在第10步,使用了自动装箱

什么时候自动拆箱

1. 初始化,赋值,函数返回时

把包装类对象赋值给基本数据类型的变量时,会自动拆箱(函数返回值原理一样)

2. 包装类型做算数运算时

算数运算(包括比较大小)是针对基本数据类型的,所以无论是基本数据类型与包装类型还是包装类型与包装类型之间做运算都会转换成两个基本数据类型

public void func3(){Integer integer = 3;int i = 1;Integer integer1 = 1;boolean b1 = integer > i; // 基本数据类型与包装类型比较大小boolean b2 = integer > integer1; // 两个包装类型比较大小}

反汇编后

public void func3();Code:0: iconst_31: invokestatic  #2                  // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;4: astore_15: iconst_16: istore_27: iconst_18: invokestatic  #2                  // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;11: astore_312: aload_113: invokevirtual #3                  // Method java/lang/Integer.intValue:()I16: iload_217: if_icmple     2420: iconst_121: goto          2524: iconst_025: istore        427: aload_128: invokevirtual #3                  // Method java/lang/Integer.intValue:()I31: aload_332: invokevirtual #3                  // Method java/lang/Integer.intValue:()I35: if_icmple     4238: iconst_139: goto          4342: iconst_043: istore        545: return

通过13步,说明基本数据类型与包装类型比较大小会转换为两个基本数据类型再比较
通过28,32步,说明两个包装类型比较大小也会转换为基本数据类型

普通的加减乘除也一样

public void func4() {Integer integer = 3;int i = 1;Integer integer1 = 1;int s = integer + integer1;int s1 = integer + i;}
public void func4();Code://...13: invokevirtual #3                  // Method java/lang/Integer.intValue:()I16: aload_317: invokevirtual #3                  // Method java/lang/Integer.intValue:()I20: iadd21: istore        423: aload_124: invokevirtual #3                  // Method java/lang/Integer.intValue:()I//...

3. 三目运算

如果三目运算的第二三位一个是基本数据类型另一个是包装类型时,会自动拆箱成两个基本数据类型

public void func5() {boolean flag = true;Integer i = 8;int j;j = 3;int k = flag ? i: j;
}
  public void func5();Code:0: iconst_11: istore_12: bipush        84: invokestatic  #2                  // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;7: astore_28: iconst_39: istore_310: iload_111: ifeq          2114: aload_215: invokevirtual #3                  // Method java/lang/Integer.intValue:()I18: goto          2221: iload_322: istore        424: return

因为i是包装类型,j是基本数据类型,所以在14行把i自动拆箱成了基本数据类型(并不是应为三目运算返回的是int),所以做三目运算时应该注意,尤其是基本数据类型和对象混杂时,如果对象没被赋值,可能导致NPL(空指针异常)

只有一个是基本数据类型,一个是包装类对象时才会自动拆箱,两个对象是不拆的。

装箱和拆箱时的缓存问题

public class Demo2 {public static void main(String[] args) {Integer a1 = 1;Integer a2 = 1;int a3 = 1;System.out.println(a1 == a2);  // trueSystem.out.println(a1.equals(a2));  // trueSystem.out.println(a1 == a3);  // trueSystem.out.println(a1.equals(a3));  // true}
}
public class Demo2 {public static void main(String[] args) {Integer a1 = 133;Integer a2 = 133;int a3 = 133;boolean b1 = a1 == a2;boolean b2 = a1.equals(a2);boolean b3 = a1 == a3;boolean b4 = a1.equals(a3);System.out.println(b1);  // falseSystem.out.println(b2);  // trueSystem.out.println(b3);  // trueSystem.out.println(b4);  // true}
}

两次结果不同,原因就是自动拆装箱时存在缓存问题,当我们第一次使用Integer时,Java会初始化一个Integer[] cache然后通过循环把-128到127之间的数加入到这个缓存中,如果新new的Integer的值在这个范围内,就直接返回这个创建好的对象,equals()比较值,==比较是不是同一对象,所以不管怎样,equals的结果都是true,而==在-128 到 127 之间是true,超出这个范围是false。

这个就类似于python中的小整数池,但python的范围是[-5, 256]

除[-128, 127]之间的整数外,boolean的两个值,以及\u0000\u007f之间的字符也在常量池中。

总结

  1. 什么是包装类

为了方便操作基本数据类型,对每一种基本类型提供一个包装类,他们将基本数据类型包装成一个对象

  1. 什么是装箱,拆箱

把基本数据类型包装成包装类的过程叫装箱(使用包装类的valueOf()方法
把包装类转换为基本数据类型的过程叫拆箱(使用包装类的xxxValue()方法

  1. 什么是自动装箱/拆箱

Java SE5 引入的一种在特定情况下将基本数据类型自动转换为包装类/包装类自动转换为基本数据类型 的机制

  1. 什么时候自动装箱

  2. Integer a = 5

  3. 函数返回值

  4. 把基本数据类型加入容器时

  5. 什么时候自动拆箱

  6. 初始化,赋值, 函数返回值

  7. 三目运算第二第三个参数既有包装类,也有基本数据类型时

  8. 算术运算,比较大小

  9. 什么是自动拆装箱时的缓存

第一次使用某些包装类时,Java会创建一个缓存池,以后每次需要包装类对象,就先会找缓存池中有没有,有就直接返回,没有才创建。缓存池的范围:

整型:[-128, 127]
布尔:[true, false]
字符:[\u0000, \u007f]

参考

什么是Java中的自动拆装箱
Java中整型的缓存机制

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/457516.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

设计模式11---组合模式(Composite Pattern)

一、组合模式定义 将对象组合成树形结构以表示“部分-整体”的层次结构&#xff0c;使得用户对单个对象和组合对象的使用具有一致性。Compose objects into tree structures to represent part-whole hierarchies. Composite lets clients treat individual objects and compos…

Linux 多核下绑定硬件中断到不同 CPU(IRQ Affinity)

转载 - Linux 多核下绑定硬件中断到不同 CPU&#xff08;IRQ Affinity&#xff09; 作者 digoal 日期 2016-11-20 标签 Linux , IRQ , 中断 , CPU亲和 , 绑定中断处理CPU 背景 原文 http://www.vpsee.com/2010/07/load-balancing-with-irq-smp-affinity/ 原文 硬件中断发生频繁…

请列举你了解的分布式锁_这几种常见的“分布式锁”写法,搞懂再也不怕面试官,安排!...

什么是分布式锁&#xff1f;大家好&#xff0c;我是jack xu&#xff0c;今天跟大家聊一聊分布式锁。首先说下什么是分布式锁&#xff0c;当我们在进行下订单减库存&#xff0c;抢票&#xff0c;选课&#xff0c;抢红包这些业务场景时&#xff0c;如果在此处没有锁的控制&#x…

leetcode 268

等差数列求值 1 class Solution {2 public:3 int missingNumber(vector<int>& nums) {4 int nnums.size();5 int kn*(n1)/2;6 for(int i0;i<n;i)7 k-nums[i];8 return k;9 } 10 }; 转载于:https://www.cnblogs.…

301缓存重定向?301 Moved Permanently (from disk cache)

今天在写一个博客系统时&#xff0c;发现首页数据经常刷新不出来&#xff0c;甚至后端根本就没有接受到这个请求&#xff0c;以为是Ajax的问题&#xff0c;但通过抓包发现Ajax请求确实已经发出去了&#xff0c;但状态码是 301 Moved Permanently (from disk cache),301是永久重…

Firefox 50优化Electrolysis

Mozilla正式发布Firefox 50。最新的版本中提升了来自多个内容进程用户的用户体验&#xff0c;并修复了十几个高影响的安全漏洞。\\在Firefox最新版本的变更中&#xff0c;我们注意到了它对于Electrolysis的进一步改进。Electrolysis是Mozilla实现在后台进程中呈现和执行web相关…

ModuleNotFoundError: No module named '_ctypes' ERROR:Command errored out with exit status 1: python

Ubuntu下载 nginx 时报错&#xff1a; ERROR: Command errored out with exit status 1:command: /usr/local/bin/python3.7 -c import sys, setuptools, tokenize; sys.argv[0] ""/tmp/pip-install-7e0xdb36/uwsgi/setup.py""; __file__""/tmp…

python opc plc_PYthon简易OPC数据采集写入Access

利用hollias comm opcserver 与Python实现交互。代码如下&#xff1a;# -*- coding: utf-8 -*-from sys import *from getopt import *#from os import * 造成f open(test.txt, r) TypeError: an integer is required错误import signalimport sysimport osimport typesimport …

边工作边刷题:70天一遍leetcode: day 73

Read N Characters Given Read4 I/II 要点&#xff1a;这题的要点就是搞清楚几个变量的内在逻辑&#xff1a;只有buffer是整4 bytes的。而client要读的bytes&#xff08;需求&#xff09;和实际上disk上有的bytes&#xff08;供给&#xff09;都是不整的。所以&#xff0c; 循环…

javascript时间戳和日期字符串相互转换

1 <html xmlns"http://www.w3.org/1999/xhtml">2 <head>3 <meta http-equiv"Content-Type" content"text/html; charsetutf-8" />4 <script type"text/javascript">5 // 获取当前时间戳(以s为单位)6 var time…

wireshark 十六进制过滤_CTF流量分析之wireshark使用

01.基本介绍在CTF比赛中&#xff0c;对于流量包的分析取证是一种十分重要的题型。通常这类题目都是会提供一个包含流量数据的pcap文件&#xff0c;参赛选手通过该文件筛选和过滤其中无关的流量信息&#xff0c;根据关键流量信息找出flag或者相关线索。pcap流量包的分析通常都是…

vim 插件管理

1  进入自己的vim mkdir ./bundle/vundle 2  在vimrc同级中执行 git clone https://github.com/gmarik/vundle.git ./bundle/vundle 将一些插件文件 下载到./bundle/vundle中 3  编写自己的vim配置&#xff0c;其实很简单 set nocompatible " be iMp…

ubuntu install wiznote

sudo add-apt-repository ppa:wiznote-team #添加官方源sudo apt-get update #更新源sudo apt-get install wiznote #安装为知笔记

python 对象序列化 pickling_python操作文件——序列化pickling和JSON

当我们在内存中定义一个dict的时候&#xff0c;我们是可以随时修改变量的内容的&#xff1a;>>> ddict(namewc,age28)>>>d{name: wc, age: 28}我们可以随时修改name和age的值。但是当我们重新运行程序的时候&#xff0c;name、age的初始化值还是wc和28&#…

python实现Redis订阅发布

Redis 发布订阅 Redis 发布订阅可以用在像消息通知&#xff0c;群聊&#xff0c;定向推送&#xff0c;参数刷新加载等业务场景 发布订阅模型有三个角色&#xff1a; 发布者&#xff08;Publisher&#xff09;订阅者(Subscriber)频道(channel) 每个订阅者可以订阅多个频道&am…

nfs的快速部署

1、nfs内核自带协议模块不用安装&#xff0c;如果没有yum安装yum -y install nfs-utils2、配置vim /etc/exports #配置文件 此文件一般为空&#xff0c;编写格式为&#xff1a; /share/word 192.168.31.254(rw) 192.168.31.252(ro) # 共享/share/word目录给192.168.…

redistemplate怎么修改数据_如何使用RedisTemplate访问Redis数据结构?

在springboot项目中&#xff0c;集成各种框架变得非常容易。下面简单介绍一下如何在springboot项目中集成单机模式redis。集群模式也差不多&#xff0c;这里就不过多介绍了。首先你得安装redis服务&#xff0c;无论在linux还是windows系统上。如果没有安装&#xff0c;请自行百…

HyperLogLog原理与在Redis中的使用

Redis-HyperLogLog 基于HyperLogLog算法&#xff0c;使用极小的空间完成巨量运算 Redis 中HyperLogLog 基本使用 常用命令 PFADD key element [element …]: 将任意数量的元素添加到指定的 HyperLogLog 里面。PFCOUNT key [key …]: 计算hyperloglog的独立总数prmerge destk…

iOS开发UI篇—xib的简单使用

一、简单介绍 xib和storyboard的比较&#xff0c;一个轻量级一个重量级。 共同点&#xff1a; 都用来描述软件界面 都用Interface Builder工具来编辑 不同点: Xib是轻量级的&#xff0c;用来描述局部的UI界面 Storyboard是重量级的&#xff0c;用来描述整个软件的多个界面&…

【云栖计算之旅】线下沙龙第2期精彩预告:Docker在云平台上的最佳实践

Docker是一个开源的应用容器引擎&#xff0c;提供了一种在安全、可重复的环境中自动部署软件的方式&#xff0c;允许开发者将他们的应用和依赖包打包到一个可移植的容器中&#xff0c;然后发布到任何流行的Linux机器上&#xff0c;也可以实现虚拟化。容器完全使用沙箱机制&…