小白的消费为何被迫升级?-java数据类型的转换
背景
小白最近有点烦恼,原因也很简单,不知道为何?小白的消费不知不觉被迫升级了,请看费用清单:
for (byte b = 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 {
public static void main(String[] args) {
byte b = 2;
int a[] = new int[b]; // dimension expression promotion
char c = '\\u0001';
a[c] = 1; // index expression promotion
a[0] = -c; // unary - promotion
System.out.println("a: " + a[0] + "," + a[1]);
b = -1;
int i = ~b; // bitwise complement promotion
System.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 {
public static void main(String[] args) {
int i = 0;
float f = 1.0f;
double d = 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:
byte b = 0x1f;
char c = 'G';
int control = 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
参考资料
【1】https://docs.oracle.com/javase/specs/jls/se12/html/jls-5.html#jls-5.1.2
小白的消费为何被迫升级?-java数据类型的转换的更多相关文章
- Java数据类型的转换:隐式(自动)转换与强制转换
原文链接:http://java.chinaitlab.com/base/725590.html 一些初学JAVA的朋友可能会遇到JAVA的数据类型之间转换的苦恼,例如,整数和float,double ...
- JAVA数据类型,变量,转换,常量,运算符
java数据类型: Java基本类型共有八种,基本类型可以分为三类: 1.字符类型char,用单引号赋值 2.布尔类型boolean 3.数值类型byte.short.int.long.float.d ...
- Java学习笔记之:Java数据类型的转换
一.介绍 数据类型的转换,分为自动转换和强制转换.自动转换是程序在执行过程中“悄然”进行的转换,不需要用户提前声明,一般是从位数低的类型向位数高的类型转换:强制类型转换则必须在代码中声明,转换顺序不受 ...
- Java数据类型及其转换&&经常用到的快捷键
数据类型 基本数据类型分类 (8种) byte .short. int. long. char. float. double .boolean 1个字节占8位 整数型byte 1字节 -128~1 ...
- Java数据类型的转换
Java数据类型,从小到大排序 byte ,short ,int ,long ,float, double,char 1.小数据类型转换大的数据类型,自动转换 int a = 3; double b ...
- JAVA数据类型自动转换,与强制转换
一.数据类型自动转换 public class Test{ public static void main(String[] args){ int a = 1; double b = 1.5; dou ...
- Java基本语法-----java数据类型的转换
前言 Java中可以进行不同数据类型的加减乘除运算吗?是可以的.在算术运算符中已经体验过如果两个整数(int)相除会去掉小数部分.如果需要保留小数部分,可以让除数或者被除数变为double类型的(5变 ...
- Java 数据类型及转换
整形: byte(1个字节) 范围:-128~127 short(2个字节) 范围:-215~215-1 (-32768~32767) int(4个字节) 范围:-231~231-1 (-214748 ...
- Java数据类型 及 转换原则
一.数据类型分类:主要分为 基本类型.引用类型两大类: 二.基本类型 转换原则 1.类型转换主要在在 赋值.方法调用.算术运算 三种情况下发生. a.赋值和方法调用 转换规则:从低位类型到高位类型自动 ...
随机推荐
- 【Java笔记】【Java核心技术卷1】chapter3 D5运算符
package chapter3; import java.math.*; //引入数学类 //枚举类型 enum Size{SMALL,MEDIUM,LARGE}; public class D5运 ...
- AWS Aurora数据库 Multi-Master 小测
AWS Aurora Mysql终于推出了Multi-Master,直面硬刚Oracle RAC.在多一份数据库产品选择的小兴奋之余,我们也看看新推出的Multi-Master的特点(包括优缺点). ...
- 原 CNN--卷积神经网络从R-CNN到Faster R-CNN的理解(CIFAR10分类代码)
1. 什么是CNN 卷积神经网络(Convolutional Neural Networks, CNN)是一类包含卷积计算且具有深度结构的前馈神经网络(Feedforward Neural Netwo ...
- 多态、继承、this、super
先放一下多态的定义: (360词典上的哈) 多态(Polymorphism)按字面的意思就是"多种状态".在面向对象语言中,接口的多种不同的实现方式即为多态.引用Charlie C ...
- curl工具使用实例
curl是一个命令行工具,其基于libcurl库,用于发送网络请求,获取并展示响应数据,下面来看curl的具体用法. 1.下载网页源码 curl命令直接接URL,用于下载指定URL的网页源码,并将其显 ...
- Struts1.x 跨站脚本(XSS)漏洞的解决
一. 演示XSS 当访问一个不存在的网址时,例如[url]http://localhost:8080/demo/noAction.do[/url],那么Struts处理后都会跳到提示“Invali ...
- Kubernetes 服务发现
目录 什么是服务发现? 环境变量 DNS 服务 Linux 中 DNS 查询原理 Kubernetes 中 DNS 查询原理 调试 DNS 服务 存根域及上游 DNS 什么是服务发现? 服务发现就是一 ...
- 如何使用Python连接ldap
如何使用Python连接ldap 好多使用ldap认证的软件都是Python的,比如superset和airflow, 好吧,他们都是airbnb家的.在配置ldap的时候可能会出现认证失败,你不知道 ...
- 最大层内元素和----leetcode周赛150_1002
题目描述: 给你一个二叉树的根节点 root.设根节点位于二叉树的第 1 层,而根节点的子节点位于第 2 层,依此类推. 请你找出层内元素之和 最大 的那几层(可能只有一层)的层号,并返回其中 最小 ...
- 数据库系统原理之SQL(三)
数据库系统原理之SQL(三) 1. SQL的组成 1. 数据查询 2. 数据定义 3. 数据操作 4. 数据控制 2. 数据定义语言 CREATE创建数据库或数据库对象 创建数据库 ~~~ CREAT ...