绑定完请刷新页面
取消
刷新

分享好友

×
取消 复制
小白的消费为何被迫升级?-java数据类型的转换
2019-12-27 10:25:51

背景

小白近有点烦恼,原因也很简单,不知道为何?小白的消费不知不觉被迫升级了,请看费用清单:

for(byteb = Byte.MIN_VALUE; b < Byte.MAX_VALUE; b++) {

if(b == 0x90)

System.out.print("life is Happy!");

}

 

本来小白预期输出结果:

life is Happy!

 

但是什么都没有输出,这是怎么回事呢?是不是以后的幸福小日子就没了?

 

于是小白向柯南请教:

 

破案

为了比较byte 数值(byte)0x90 和int 数值0x90,Java 通过拓宽原始类型转换

将byte 提升为一个int[JLS 5.1.2],然后比较这两个int 数值。0x90为144,但byte指的范围为-128~127

故没有打印出预期的值。

究根到底

原来java language Specification中有自动Promotion机制,让我们了解一下数字提升的问题吧

数字提升总体的规则是向上提升,又分为一元数字提升和二元数字提升

一元数字提升

某些运算符将一元数值提升用在了单操作数运算中,其必定能得到一个数字类型的值,

规则如下:

if 操作数是编译时包装类型Byte、Short、Character或Integer,那么它会先拆箱为对应的原始类型,然后拓宽为int类型。

else if 操作数为编译时包装类型Long、Float或Double,那么就直接拆箱为对应的原始类型。

else if 操作数是编译时拆箱类型byte、short、char或int,那么就拓宽为int类型。

else 保持原样。

一元数值提升还用在以下情境的表达式中:

数组创建表达式的维度

数组索引表达式的索引

正号运算符(+)的操作数

负号运算符(-)的操作数

按位补运算符(~)的操作数

移位运算符(>>, >>>, << )的每一个操作数。注意移位运算并不会使两边的操作数提升到相同类型,如 A << B 中若B为long类型,A并不会被提升到long。

是不是很难理解?

 

那就举个例子吧

 

class Test {

publicstaticvoid main(String[] args) {

byteb = 2;

inta[] =newint[b];// dimension expression promotioncharc = '\\u0001';

a[c] = 1;// index expression promotiona[0] = -c;// unary - promotionSystem.out.println("a: " + a[0] + "," + a[1]);

b = -1;

inti = ~b;// bitwise complement promotionSystem.out.println("~0x" + Integer.toHexString(b)

+ "==0x" + Integer.toHexString(i));

i = b << 4L;// shift promotion (left operand)System.out.println("0x" + Integer.toHexString(b)

+ "<<4L==0x" + Integer.toHexString(i));

}

}

 

输出结果为:

a: -1,1

~0xffffffff==0x0

0xffffffff<<4L==0xfffffff0

二元数字提升

当二元运算符的操作数皆可转化为数字类型时,那么将采用如下二元数值提升规则:

如果任一操作数为引用类型,那么对其进行自动拆箱。

拓宽类型转换被应用于以下情况:

if 某一操作数为double类型,那么另一个也转为double

else if 某一操作数为float类型,那么另一个也转为float

else if 某一操作数为long类型,那么另一个也转为long

else 两个操作数都转为int

应用场景

乘除法运算符: * 、 / 、%

针对数字类型的加减运算符: + 、 -

数值比较运算符:< 、<= 、> 、>=

数值相等比较运算符: == 、 !=

整数按位运算符: & 、^ 、|

某些情况下的条件运算符 ? : 中

来个例子吧

class Test {

publicstaticvoid main(String[] args) {

inti = 0;

floatf = 1.0f;

doubled = 2.0;

// First int*float is promoted to float*float, then

// float==double is promoted to double==double:if(i * f == d) System.out.println("oops");

// A char&byte is promoted to int&int:byteb = 0x1f;

charc = 'G';

intcontrol = c & b;

System.out.println(Integer.toHexString(control));

// Here int:float is promoted to float:float:f = (b==0) ? i : 4.0f;

System.out.println(1.0/f);

}

}

 

其实上面的都是冰山一角罢了

 

更多信息可以查看jls Chapter 5. Conversions and Contexts

分享好友

分享这个小栈给你的朋友们,一起进步吧。

JAVA玩具小屋
创建时间:2019-08-16 16:54:49
分享程序开发方面的小经验,思考一些比较简单易懂的技术问题
展开
订阅须知

• 所有用户可根据关注领域订阅专区或所有专区

• 付费订阅:虚拟交易,一经交易不退款;若特殊情况,可3日内客服咨询

• 专区发布评论属默认订阅所评论专区(除付费小栈外)

栈主、嘉宾

查看更多
  • Yios5092
    栈主

小栈成员

查看更多
  • 栈栈
  • coyan
  • 25minutes
  • ?
戳我,来吐槽~