【Java核心技术卷】深入了解Java的类型转换(低位丢失,高位溢出等问题)

文章目录

    • 关于Java的两种类型转换:
      • 强类型转换
      • 隐式类型转换

关于Java的两种类型转换:

第一种是强类型转换,第二种是弱类型转换.
每种类型转换都存在着一定的风险,只有清晰地去认识它们,才能够少犯错误

强类型转换

强类型转换出现的有效位数低位数据丢失(将出现逻辑错误)、范围的高位溢出(将出现异常).
这些错误是由程序员负责的,这就需要我们在进行强制类型转换的时候,要多加注意

下面让我们看一下低位丢失和高位溢出的情况

public class demo {
	public static void main(String[] args) {
		int x;
		float y=11111111111.0f;
		x = (int)11.1 +(int)22.2; //低位丢失
		System.out.println(" "+x);
		x = (int)y;
		System.out.println(" "+x);
	}
}

结果为:
【Java核心技术卷】深入了解Java的类型转换(低位丢失,高位溢出等问题)_第1张图片
对于低位丢失,应该很好理解,不少朋友也知道高位溢出是怎么回事,就是容量不够了呗,那么解释为什么结果是2147473647却说不太清楚
那么让我们详细看看这是什么情况

我们知道int在任何操作系统上的Java都是4个字节,也就是32位
二进制范围: -2^31 ~ 2^31 – 1
十进制范围: -2147483648 ~ 2147483647
最大十进制有效位数:10(整数部分最多不超过10位,多于10位的数字强制转化为int类型,就会出现高位溢出)


类似的:
byte(1字节) D7----------------D0
采用补码存储
二进制范围: -27 ~ +(27 – 1)
十进制范围: -128 ~ 127
最大十进制有效位数: 3

short(2字节) D15----------------D0
采用补码存储
二进制范围: -215 ~ +(215 – 1)
十进制范围: -32768 ~ 32767
最大十进制有效位数: 5

int(4字节) D31----------------D0
采用补码存储
二进制范围: -231 ~ +(231 – 1)
十进制范围: -2147483648 ~ 2147483647
最大十进制有效位数: 10

long(8字节) D63----------------D0
采用补码存储
二进制范围: -263 ~ +(263 – 1)
十进制范围: -9223772036854775808 ~ 9223772036854775807
最大十进制有效位数: 19

char(2字节) D15----------------D0
采用无符号存储:unsigned short
二进制范围: 0 ~ +(216 – 1)
十进制范围: 0 ~ 64335
最大十进制有效位数: 5

float(4字节) D15----------------D0
采用IEEE754单精度浮点数格式存储
最大二进制有效位数: D23----------------D0
最大十进制有效位数: 8

double(8字节) D63----------------D0
采用IEEE754双精度浮点数格式存储
二进制范围:
最大值为1 x (253 - 1) x 2971
最小为1 x 2-1074
十进制范围:
最大值为±1.7976931348623157 x 10308,
最小为±5 x 10-324
Number.MAX_VALUE:1.7976931348623157 x 10308 (最大表示数,理解为最大值)
Number.MIN_VALUE:5 x 10-324 (最大\小表示数,理解为最小值)
Number.NEGATIVE_INFINITY:-Infinity
Number.POSITIVE_INFINITY:Infinity
Number.NaN:NaN
最大二进制有效位数: D53----------------D0
最大十进制有效位数: 17

隐式类型转换

所谓隐式类型转换就是下图的规则:
【Java核心技术卷】深入了解Java的类型转换(低位丢失,高位溢出等问题)_第2张图片

高位不会出现溢出,但是可能出现有效位数低位丢失(如下图中的虚线所示),将隐式出现逻辑错误由程序员负责。
虚线的地方 要多加注意
注意整型(long) 与 float类型 一同运算的时候,要将long类型转换成float类型

【Java核心技术卷】深入了解Java的类型转换(低位丢失,高位溢出等问题)_第3张图片
上面这张图是我们引入的模型
y 表示最大十进制的位数
x 表示二进制的有效位数
比如说 float类型
image
尾数位的23位为二进制的有效位数 第32位是符号位,紧挨着的8位是 指数位
对于 int 类型第32位是符号位 其它31位是二进制的有效位数
int 2进制的有效位数 > float 2进制的有效位数
但是 int 最大十进制有效位数 小于 float 最大十进制有效位数 (也就是int 最大值 < float 最大值)
通俗点讲:
拿31位的有效位数字放到23位的有效数字中肯定不行呀
但是要注意的是int 值总的范围大小是2的32次方,而float类型因为有8位指数位,所以要大得多.

建立下面模型:
【Java核心技术卷】深入了解Java的类型转换(低位丢失,高位溢出等问题)_第4张图片
同理:
【Java核心技术卷】深入了解Java的类型转换(低位丢失,高位溢出等问题)_第5张图片

隐式类型转换可能出现低位丢失情况:
1、运算表达式
x(int) + y(float)
2、赋值表达式
y(float) = x(int)7
上面介绍过了

开始介绍下面的
3、方法调用,实参到形参的传递
方法定义:f( float y )
方法调用:o.f(x(int) )

举个例子:

//Application.java
class Person {
 
	int ID;
	int age;
 
	Person(int ID,int age) {
		this.ID = ID;
		this.age = age;
	}
 
	void intfloat(int x,float y) {
		System.out.println("float y =" + y + ",int x=" + x);
	}
	
}
 
public class Application {
 
	public static void main(String[] args) {
		Person p = new Person(1,21);
 
		int x = 12345678;
		float y = 0;
 
		System.out.println("------------int,float均在重叠范围---------------");
 
		//1.赋值表达式
		//输出:float y = 1.2345678E7,int x = 12345678
		y = x;
		System.out.println("float y =" + y + ",int x=" + x);
 
		//2.算术运算表达式
		//输出:float y = 1.2345678E7,int x = 12345678
		y = 0;
		y = y + x;
		System.out.println("float y =" + y + ",int x=" + x);
 
		//3.方法调用表达式实参到形参的传递
		//输出:float y = 1.2345678E7,int x = 12345678
		p.intfloat(x,x);
 
 
		System.out.println("------------int,float不在重叠范围---------------");
 
		x = 123456789;
		y = 0;
 
		//1.赋值表达式,出现低位丢失,丢失时的四舍五入
		//输出:float y = 1.23456792E8,int x = 123456789
		y = x;
		System.out.println("float y =" + y + ",int x=" + x);
 
		//2.算术运算表达式,出现低位丢失,丢失时的四舍五入
		//输出:float y = 1.23456792E8,int x = 123456789
		y = 0;
		y = y + x;
		System.out.println("float y =" + y + ",int x=" + x);
 
		//3.方法调用表达式实参到形参的传递 ,出现低位丢失,丢失时的四舍五入
		//输出:float y = 1.23456792E8,int x = 123456789
		p.intfloat(x,x);
	}
}

【Java核心技术卷】深入了解Java的类型转换(低位丢失,高位溢出等问题)_第6张图片
这是结果

你可能感兴趣的:(Java核心技术)