0
点赞
收藏
分享

微信扫一扫

Java数值类型提升机制

【1】数值提升

数字类型提升机制被用于算术运算符上,通常使用场景为:

  • 同一类型转换
    有时可以使代码更清晰。
  • 拓宽原始类型转换
    指byte、short、int、long、float、double由低向高转换。
  • 自动拆箱转换
    基础类型引用类的拆箱方法,如r.intValue()。

数值提升用于将算术运算中的操作数转化为一个相同的类型以便于运算,具体分为两种情况:一元数值提升和二元数值提升。

【2】一元数值提升

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

  • if 操作数是编译时包装类型​​Byte、Short、Character或Integer​​,那么它会先拆箱为对应的原始类型,然后拓宽为int类型。
  • else if 操作数为编译时包装类型​​Long、Float或Double​​,那么就直接拆箱为对应的原始类型。
  • else if 操作数是编译时拆箱类型​​byte、short、char或int​​,那么就拓宽为int类型。
  • else 保持原样。

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

  • 数组创建表达式的维度
  • 数组索引表达式的索引
  • 正号运算符(+)的操作数
  • 负号运算符(-)的操作数
  • 按位补运算符(~)的操作数
  • 移位运算符(>>, >>>, << )的每一个操作数。注意移位运算并不会使两边的操作数提升到相同类型,如 A << B 中若B为long类型,A并不会被提升到long。

注意:自增和自减单目运算符同样也会进行类型提升,但运算后会自动进行强制类型转换,如
byte a = 127;
a++; // a在运算后为int类型,转为byte截断后变成-128
等价于
byte a = (byte)128;

示例如下:

class Test {
public static void main(String[] args) {
byte b = 2;
int a[] = new int[b]; // 维度表达式提升
char c = '\u0001';
a[c] = 1; // 索引表达式提升
a[0] = -c; // 负号 提升
System.out.println("a: " + a[0] + "," + a[1]);
b = -1;
int i = ~b; // 按位补提升
System.out.println("~0x" + Integer.toHexString(b)
+ "==0x" + Integer.toHexString(i));
i = b << 4L; // 移位提升(左操作数)
System.out.println("0x" + Integer.toHexString(b)
+ "<<4L==0x" + Integer.toHexString(i));
}
}

输出:
a: -1,1
~0xffffffff==0x0
0xffffffff<<4L==0xfffffff0

【3】二元数值提升

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

  • 如果任一操作数为引用类型,那么对其进行自动拆箱。
  • 拓宽类型转换被应用于以下情况:
  • if 某一操作数为double类型,那么另一个也转为double
  • else if 某一操作数为float类型,那么另一个也转为float
  • else if 某一操作数为long类型,那么另一个也转为long
  • else 两个操作数都转为int

二元数值提升应用于以下运算符上:

  • 乘除法运算符: * 、 / 、%
  • 针对数字类型的加减运算符: + 、 -
  • 数值比较运算符:< 、<= 、> 、>=
  • 数值相等比较运算符: == 、 !=
  • 整数按位运算符: & 、^ 、|
  • 某些情况下的条件运算符 ? : 中

注意:混合赋值运算符同样也会自动进行强制类型转换,如
byte a = 127;
a += 1; // a在运算后为int类型,转为byte截断后变成-128

示例如下:

class Test {
public static void main(String[] args) {
int i = 0;
float f = 1.0f;
double d = 2.0;
// int*float 先是被提升为 float*float,然后
// float==double 被提升为 double==double:
if (i * f == d) System.out.println("oops");

// char&byte 被提升为 int&int:
byte b = 0x1f;
char c = 'G';
int control = c & b;
System.out.println(Integer.toHexString(control));

// 此处 int:float 被提升为 float:float:
f = (b==0) ? i : 4.0f;
System.out.println(1.0/f);
}
}

输出:
7
0.25

条件运算符中的类型提升 【4】进制

① 十进制(最常用的进制)

  • 十进制就是满十进一的进制
  • 十进制当中一共有10个数字
    0 1 2 3 4 5 6 7 8 9
  • 十进制如何计数
    0 1 2 3 4 5 6 7 8 9 10 11 12 。。。 19 20 。。。29 30

② 二进制(计算机底层使用的进制)

  • 满二进一
  • 二进制中一共有2个数字
    0 1
  • 二进制如何计数
    0 1 10 11 100 101 110 111 1000
  • 所有的数据在计算机底层都是以二进制的形式保存的,计算机只认二进制
  • 可以将内存想象为一个一个的小格子,小格子中可以存储一个0或一个1
  • 内存中的每一个小格子,我们称为1bit(位)
    bit是计算机中的最小的单位
    byte是我们最小的可操作的单位
    8bit = 1byte(字节)
    1024byte = 1kb(千字节)
    1024kb = 1mb(兆字节)
    1024mb = 1gb(吉字节)
    1024gb = 1tb(太字节)

③ 八进制(一般不用)

  • 满八进一
  • 八进制中一共有8个数字
    0 1 2 3 4 5 6 7
  • 八进制如何计数
    0 1 2 3 4 5 6 7 10 11 。。。 17 20 。。。27 30

④ 十六进制

  • 满十六进一
  • 十六进制中一共有16个数字
    由于十六进制是满16才进位,
    所以十六进制中引入了a b c d e f来表示 10 11 12 13 14 15
    0 1 2 3 4 5 6 7 8 9 a b c d e f
  • 十六进制如何计数
    0 1 2 3 4 5 6 7 8 9 a b c d e f 10 11 12 。。。 1a 1b 1c 1d 1e 1f
    20 21 22 。。。 2a 2b 2c 2d 2e 2f 30
  • 我们在查看二进制数据时,一般会以十六进制的形式显示


举报

相关推荐

0 条评论