您当前的位置:首页 > 电脑百科 > 程序开发 > 编程百科

灵魂拷问:为什么short、byte会被提升为int?boolean到底多大?

时间:2020-07-17 10:39:48  来源:  作者:
灵魂拷问:为什么short、byte会被提升为int?boolean到底多大?

 

为什么short、byte会被提升为 int ?

在学习JAVA语法的时候,知道short 、byte、byte 类型在做运算符号的时候,都会默认提升为 int,例如下面的代码就是无法通过编译的,需要将等于号右边的强制转为 short 才可以。

public static void main(String[] args) {    short a = 1;    short b = 2;    a = a + b;           // 编译不过    short c = a + b;  // 编译不过}

为什么两个 short 相加会变成 int,有的人解释说,两个 short 相加可能溢出,所以用 int 来接就不会溢出,那这样的话,两个 int 相加岂不应该是 long 类型吗?其实本质的原因要从字节码开始讲起。

Java虚拟机的指令由一个字节长度的、代表着某种特定操作含义的数字(称为操作码,Opcode)以及跟随其后的零至多个代表次操作所需参数(称为操作数,Operands)而构成。

Java虚拟机的指令集中的大多数都对它们执行的操作的数据类型进行编码,例如 iload 指令,是将一个局部变量加载到操作栈,且这个局部变量必须是 int 类型。

由于操作码的长度为一个字节,这意味着指令集的操作码总数不可能超过256条,这也为设计包含数据类型的操作码带来了很大压力:如果每一种与数据类型相关的指令都支持Java虚拟机所有运行时数据类型的话,那指令的数量就会超出一个字节所能表示的数量范围了。

根据下表(出自 Table 2.11.1-A. Type support in the Java Virtual machine instruction set),可以发现大部分指令都没有支持 byte、char 和 short 类型,甚至没有任何指令支持 boolean 类型。编译器会在编译器或运行期将 byte 和 short 类型带符号扩展为 int 类型, boolean 和 char 类型零位扩展为相应的 int 类型。与之类似,在处理 boolean、byte、char 和 short 类型的数组时,也会转为使用相应的 int 类型的字节码来处理指令。 因此,大多数对于 boolean、byte、char 和 short 类型数据的操作,实际都是使用 int 类型作为运算类型。另外还有第二点原因,在设计虚拟机时,主要考虑的是 32位体系,32位系统使用 4 字节是最节省,因为 CPU 只能 32位32位的寻址。

如果想详细查看各个指令,可以参考Java虚拟机规范

灵魂拷问:为什么short、byte会被提升为int?boolean到底多大?

 

Java 中 boolean 到底多大?

我们继续深入思考, boolen 到底有多大? 在学 Java 的时候, 都说 byte、boolen 类型占 1字节,但上面又提到, byte 会被提升为 int 类型,那么就应该占了 4字节。没错,虚拟机规范只有 4字节 和 8字节类型(long、float), boolean、char、short 都是占了 4字节。

我们来看一例子。

public class Test {    byte aByte = 2;    short aShort = 3;        public void byteAdd() {        aByte = (byte) (aByte + 1);    }    public void shortAdd() {        aShort = (short) (aShort + 1);    }}

先编译此文件javac Test.java,查看 Class 内容,javap -verbose Test,摘取关键信息:

{  byte aByte;    descriptor: B    flags:  short aShort;    descriptor: S    flags:  public void byteAdd();    descriptor: ()V    flags: ACC_PUBLIC    Code:      stack=3, locals=1, args_size=1         0: aload_0         1: aload_0         2: getfield      #2                  // Field aByte:B         5: iconst_1         6: iadd         7: i2b         8: putfield      #2                  // Field aByte:B        11: return  public void shortAdd();    descriptor: ()V    flags: ACC_PUBLIC    Code:      stack=3, locals=1, args_size=1         0: aload_0         1: aload_0         2: getfield      #3                  // Field aShort:S         5: iconst_1         6: iadd         7: i2s         8: putfield      #3                  // Field aShort:S        11: return}

观察这两个方法,第一第二行目的是将对应的变量压入栈,第五行都是 iconst_1,将 int 类型的 1 压入栈中,然后使用 iadd 方法,将两个值相加,之后一个调用 i2b,一个调用 i2s 指令。我们随便查看一个i2s的命令介绍 jvms-6.5.i2s,它是这样描述的

The value on the top of the operand stack must be of type int. It is popped from the operand stack, truncated to a short, then sign-extended to an int result. That result is pushed onto the operand stack.

翻译过来大致是:

操作数堆栈顶部的值必须是int类型。它从操作数堆栈中弹出,截断为short,然后符号扩展为int结果。结果被推送到操作数堆栈上。

因此,可以看出 short、char 实际上也是占用了 和 int 一样大的字节的。那我们平时所说 short 是 2 字节的岂不是错误的?并不是,对于单个 byte、char、short 类型的数据,在内存中实际会占 4 字节,但这对于数组来说并不适用, byte 数组每个元素占 1 字节, char、short 数组都占 2 字节。

参考stackoverflow中的回答 Size of a byte in memory - Java,注意标注高亮的部分。

更多对基本类型的描述,可以查看Primitive Data Types

说完byte、char、short,我们再来看看对于 boolean 的描述,摘取部分信息 2.3.4. The boolean Type:

Although the Java Virtual Machine defines a boolean type, it only provides very limited support for it. There are no Java Virtual Machine instructions solely dedicated to operations on boolean values. Instead, expressions in the Java programming language that operate on boolean values are compiled to use values of the Java Virtual Machine int data type.

 

The Java Virtual Machine does directly support boolean arrays. Its newarray instruction (§newarray) enables creation of boolean arrays. Arrays of type boolean are accessed and modified using the byte array instructions baload and bastore (§baload, §bastore).

 

In Oracle’s Java Virtual Machine implementation, boolean arrays in the Java programming language are encoded as Java Virtual Machine byte arrays, using 8 bits per boolean element.

翻译大概如下:

尽管Java虚拟机定义了一种 boolean 类型,但对它的提供支持非常有限,没有专门的虚拟机指令用来操作 boolean 类型。但是,对于有 boolean 值参与运行的表达式,都会被编译成 int 类型的数据。

 

虚拟机直接支持了 boolean 数组,它使用newarray指令来创建数组,并可以使用 baload 和 bastore 来访问和修改 boolean 类型的数组

 

在 Oracle 的Java虚拟机实现中, boolean 类型的数组被编码成和 byte类型的数组, 每个 boolean 元素使用 8 bit。

所以虚拟机规范是这样定义的:boolean 单独使用时,占 4 字节,在数组中使用时,占 1 字节。但最终如何实现,还是要看各个虚拟机厂商是否遵守规范了。



Tags:boolean   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,如有任何标注错误或版权侵犯请与我们联系(Email:2595517585@qq.com),我们将及时更正、删除,谢谢。
▌相关推荐
为什么short、byte会被提升为 int ?在学习Java语法的时候,知道short 、byte、byte 类型在做运算符号的时候,都会默认提升为 int,例如下面的代码就是无法通过编译的,需要将等于号...【详细内容】
2020-07-17  Tags: boolean  点击:(31)  评论:(0)  加入收藏
▌简易百科推荐
摘 要 (OF作品展示)OF之前介绍了用python实现数据可视化、数据分析及一些小项目,但基本都是后端的知识。想要做一个好看的可视化大屏,我们还要学一些前端的知识(vue),网上有很多比...【详细内容】
2021-12-27  项目与数据管理    Tags:Vue   点击:(1)  评论:(0)  加入收藏
程序是如何被执行的  程序是如何被执行的?许多开发者可能也没法回答这个问题,大多数人更注重的是如何编写程序,却不会太注意编写好的程序是如何被运行,这并不是一个好...【详细内容】
2021-12-23  IT学习日记    Tags:程序   点击:(9)  评论:(0)  加入收藏
阅读收获✔️1. 了解单点登录实现原理✔️2. 掌握快速使用xxl-sso接入单点登录功能一、早期的多系统登录解决方案 单系统登录解决方案的核心是cookie,cookie携带会话id在浏览器...【详细内容】
2021-12-23  程序yuan    Tags:单点登录(   点击:(8)  评论:(0)  加入收藏
下载Eclipse RCP IDE如果你电脑上还没有安装Eclipse,那么请到这里下载对应版本的软件进行安装。具体的安装步骤就不在这赘述了。创建第一个标准Eclipse RCP应用(总共分为六步)1...【详细内容】
2021-12-22  阿福ChrisYuan    Tags:RCP应用   点击:(7)  评论:(0)  加入收藏
今天想简单聊一聊 Token 的 Value Capture,就是币的价值问题。首先说明啊,这个话题包含的内容非常之光,Token 的经济学设计也可以包含诸多问题,所以几乎不可能把这个问题说的清...【详细内容】
2021-12-21  唐少华TSH    Tags:Token   点击:(9)  评论:(0)  加入收藏
实现效果:假如有10条数据,分组展示,默认在当前页面展示4个,点击换一批,从第5个开始继续展示,到最后一组,再重新返回到第一组 data() { return { qList: [], //处理后...【详细内容】
2021-12-17  Mason程    Tags:VUE   点击:(14)  评论:(0)  加入收藏
什么是性能调优?(what) 为什么需要性能调优?(why) 什么时候需要性能调优?(when) 什么地方需要性能调优?(where) 什么时候来进行性能调优?(who) 怎么样进行性能调优?(How) 硬件配...【详细内容】
2021-12-16  软件测试小p    Tags:性能调优   点击:(19)  评论:(0)  加入收藏
Tasker 是一款适用于 Android 设备的高级自动化应用,它可以通过脚本让重复性的操作自动运行,提高效率。 不知道从哪里听说的抖音 app 会导致 OLED 屏幕烧屏。于是就现学现卖,自...【详细内容】
2021-12-15  ITBang    Tags:抖音防烧屏   点击:(23)  评论:(0)  加入收藏
11 月 23 日,Rust Moderation Team(审核团队)在 GitHub 上发布了辞职公告,即刻生效。根据公告,审核团队集体辞职是为了抗议 Rust 核心团队(Core team)在执行社区行为准则和标准上...【详细内容】
2021-12-15  InfoQ    Tags:Rust   点击:(24)  评论:(0)  加入收藏
一个项目的大部分API,测试用例在参数和参数值等信息会有很多相似的地方。我们可以复制API,复制用例来快速生成,然后做细微调整既可以满足我们的测试需求1.复制API:在菜单发布单...【详细内容】
2021-12-14  AutoMeter    Tags:AutoMeter   点击:(20)  评论:(0)  加入收藏
相关文章
    无相关信息
最新更新
栏目热门
栏目头条