Java中两个byte类型相加结果赋值给byte类型的变量会报编译错误,byte加byte的结果为什么是int?

背景:

之前偶然看到有讨论这个问题,在网上搜了半天,结果都不尽如人意,解释没有到位,

有的说byte加byte默认就是int,那为什么这么做呢? 这不是找麻烦么?这种奇怪的默认还有哪些?带来一些列疑问。。。。。。

有的说byte存储的就是整型数据,这种说法的对错姑且不论,至少我觉得难免有点牵强了,还是疑问重重。。

所以今天专门总结一下:

----------------------------------------------------------------------------------------------------------------------------------------------------------------

一、问题:

先看这段代码:

(1)  byte a=1;
(2)  byte b=2;
(3)  byte d=-1;
(4)  byte c=128;  //编译错误,因为byte类型的数据是单字节,表示十进制数的范围是-128~+127(第一位是符号位,代表正负数)
    		
(5)  a = a+b;//编译错误,byte+byte的结果不是byte类型,提示需要强制转换为byte类型或者把等式左边类型改编为int.
    		
(6)  a = (byte)(a+b);

(1)(2)(3)行,正常赋值操作,没有问题;

(4)行,编译错误,实际上是因为byte类型的数据是单字节,表示十进制数的范围是-128~+127;

(5)行,就是今天的重点了,也报了编译错误,byte+byte的结果不是byte类型,反而提示需要强制转换为byte类型或者把等式左边类型改编为int.  就如第(6)行那样。  这就像两个人站在一起,需要有人强制解释一下,别人才知道这是两个人,而不是其他的什么东西,这也太奇怪了!

 

二、对背后原因的探索:

       要了解清楚这个问题的原因,必须要从Java虚拟机的指令集说起,每种指令代表了一种操作。

        首先要说明的是:在Java虚拟机中,对于大部分与数据类型相关的字节码指令,他们的操作码助记符中都有特殊的字符来表示专门为哪种数据类型服务。

        但是Java虚拟机的操作码长度只有一个字节,这就带来一个问题,如果每种与数据类型相关的指令都支持Java虚拟机运行时数据类型的话,显然一个字节就不够用了。  所以Java虚拟机规范中,这种特性"Not Orthogonal",并非每种数据类型和每一种操作都有对应的指令。

        大部分的指令都没有支持byte、char、short,没有任何指令支持boolean类型。编译器在编译期或者运行期将byte和short类型的数据带符号扩展为相应的int类型数据,将boolean和char类型数据零位扩展为相应的int类型数据。与之类似的,在处理byte、char、short和boolean类型的数组时,也会转换成对应的int类型的字节码指令来处理。因此,大多数对于byte、char、short和boolean类型数据的操作,实际上都是使用相应的int类型作为运算类型的。

 

参考书籍:《深入理解Java虚拟机:JVM高级特性与最佳实践》(第三部分,第6章,6.4.1小节:P197-P199 关于Java虚拟机指令集所支持的数据类型相关的内容)

 

 

 

  • 18
    点赞
  • 37
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
支持下载,一、数据类型 常量是有数据类型变量必须声明其数据类型 (1)划分: 1.基本数据类型(四类八种) 数值型: 整数型:bute、short、int、long 浮点型:float、double 字符型:char 布尔型:boolean 2.引用数据类型:除基本数据类型外的所有都是基本数据类型 数值型: 类型 所占空间 取值范围 默认值 字节型 byte 1个字节(8位) -128—127 0 短整型 short 2个字节(16位) -32768—32767 0 整形 int 4个字节(32位) +-2(的31次方)约21亿 0 长整形 long 8个字节(64位) -2(的63次方)—2(的63次方)-1 0 浮点型: 单精度浮点型 float 4个字节(32位) 1.4013E-45—3.4028E+38 0.0F 双精度浮点型 double 8个字节(64位) 4.9E-324—1.7977E+308 0.0D 字符型: 字符型 char 2个字节(16位) 0—2(的16次方)-1 \u0000 布尔型: 布尔型 boolean 1个字节(8位) ture,false false (2)整形常量常用的三种表现形式: 1.二进制 2.八进制:八进制的数以0开头 3.十六进制:十六进制的以0x开头,0ffff:一个f代表4位 二、类型的转换 1.自动转换 2.强制转换 在一个表达式,先把所有数转换成为级别最高的那个类型之后,再进行运算 byte,short,char 只要在表数范围,不用强转可以直接进行赋值。但是要是超出范围,就必须要进行强转了 类型的优先级别:byte,short,char,int,long,float,double (低–高) 右>左–强制类型转换 右<左–自动转换 右=左–不用转 三、运算符: 算术运算符: +,-,*,/,%,++,– 赋值运算符:= 关系运算符: >,<,>=,<=,==,!= instanceof 逻辑运算符: &&,||,!,^ 位运算符: &,|,^,~ , >>,<<,>>> 条件运算符:?:(三目运算符) 扩展赋值运算符:+=,-=,*=,/= 1.算数运算符(+,-,*,/,%,++,–) (1) 两个int类型数据运算,结果是int类型 两个操作数只要有一个是double类型,那么结果是double类型的数据 (2) “+”号的作用 1.表示正数 2.相加运算 3.字符串拼接 在单独运算的时候 ++i,i++ 没有任何区别,都是1操作相当于 i=i+1 i++;先运算,后1(先运算后减) ++i;先1,后运算(先减后运算) 2.逻辑运算符(&&,||,!,^) 逻辑非 ! 取反 逻辑异或 ^ 操作数一样,结果为false;操作数不一样,结果为true 逻辑与 & 只要有一个操作数是false,那么结果就是false 短路与 && 短路与跟逻辑与 结果会一模一样。只要第一个操作数是false,那么结果一定是false,那么后面的那个操作数就不用计算了。提高了 效率。 逻辑或 | 只要有一个是true,那么结果就是true 短路或 || 短路或与逻辑或 结果一模一样。只要第一个操作数是true,那么第二个就不用计算,结果就是true。同样为了提高效率。 3.关系运算符(>,<,>=,<=,==,!=) ==:比较变量时是判断数值是否相等;比较引用变量时是判断两个在堆的存储的地址是否相等 equals:操作时是判断两个变量是否是对同一对象的引用,即对堆的内容进行比较 在比较引用变量时: ==判断的对象的地址 equals判断的是对象的内容 4.位运算符( &,|,^,~ , >>,<<,>>>) 在操作十进制数的时候首先转换为二进制的数进行操作 &:二进制都为1时为1,一个为0则为0 |:二进制都为0时为0,一个为1则为1 ^:二进制都为1时为0,一个为0则为1 ~:一个正数取~时,取反、减一、取反、符号 一个负数取~时,直接取反
abstract (关键字) 抽象 ['æbstrækt] access vt.访问,存取 ['ækses]'(n.入口,使用权) algorithm n.算法 ['ælgәriðm] Annotation [java] 代码注释 [ænәu'teiʃәn] anonymous adj.匿名的[ә'nɒnimәs]'(反义:directly adv.直接地,立即[di'rektli, dai'rektli]) apply v.应用,适用 [ә'plai] application n.应用,应用程序 [,æpli'keiʃәn]' (application crash 程序崩溃) arbitrary a.任意的 ['ɑ:bitrәri] argument n.参数;争论,论据 ['ɑ:gjumәnt]'(缩写 args) assert (关键字) 断言 [ә'sә:t] ' (java 1.4 之后成为关键字) associate n.关联(同伴,伙伴) [ә'sәuʃieit] attribute n.属性(品质,特征) [ә'tribju:t] boolean (关键字) 逻辑的, 布尔型 call n.v.调用; 呼叫; [kɒ:l] circumstance n.事件(环境,状况) ['sә:kәmstәns] crash n.崩溃,破碎 [kræʃ] cohesion 内聚,黏聚,结合 [kәu'hi:ʒәn] (a class is designed with a single, well-focoused purpose. 应该不止这点) command n. 命令,指令 [kә'mɑ:nd](指挥, 控制) (command-line 命令行) Comments [java] 文本注释 ['kɒments] compile [java] v.编译 [kәm'pail]' Compilation n.编辑[,kɒmpi'leiʃәn] const (保留字) constant n. 常量, 常数, 恒量 ['kɒnstәnt] continue (关键字) coupling 耦合,联结 ['kʌpliŋ] making sure that classes know about other classes only through their APIs. declare [java] 声明 [di'klєә] default (关键字) 默认值; 缺省值 [di'fɒ:lt] delimiter 定义符; 定界符 Encapsulation[java] 封装 (hiding implementation details) Exception [java] 例外; 异常 [ik'sepʃәn] entry n.登录项, 输入项, 条目['entri] enum (关键字) execute vt.执行 ['eksikju:t] exhibit v.显示, 陈列 [ig'zibit] exist 存在, 发生 [ig'zist] '(SQL关键字 exists) extends (关键字) 继承、扩展 [ik'stend] false (关键字) final (关键字) finally (关键字) fragments 段落; 代码块 ['frægmәnt] FrameWork [java] 结构,框架 ['freimwә:k] Generic [java] 泛型 [dʒi'nerik] goto (保留字) 跳转 heap n.堆 [hi:p] implements (关键字) 实现 ['implim

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值