为什么Java在数据类型强制转换过程中,超过转换数据类型的取值范围则值为负数?
要从根本上了解这个过程和原理,需要了解两个知识点:Java类型转换与二进制
一、Java类型转换
Java是一种强类型语言,使用变量前需要声明对象类型;在实际开发过程中,常常会涉及到数据类型的转化。
数据类型的转化分为两种,一种是隐式转换:
public class testCode {
public static void main (String[]args){
char char_1 = 'a';
int number_2 = char_1 + 1;
System.out.println(number_2);
}
}
在int number_2 = number_1 + 1;
的过程中,最开始声明为char类型的char_1
会隐式的转化为int类型,而小写的a
对应的ASSIC的码十进制为97,故char_1 + 1
结果为98。
运行结果:
自动转换虽然方便,但是严格遵守转换规律(低转高):
byte > short > int > long >float > double
char > int > long >float > double
如果想要想要将一个float类型的数值,转化为int类型,则需要用到强制转换(高转低):
public class testCode {
public static void main (String[]args){
float float_1= 3.1415926F;
//强制转换格式:数据类型 变量名 = (转换类型) 被转换的变量;
int number_2 = (int) float_1;
System.out.println(number_2);
}
}
虽然强制转换不难,但是转换过程涉及到一个大大的问题:精度丢失!
3.1415926直接被一刀切成整数3,出现这个情况的原因和超过转换数据类型的取值范围则值为负数的原因大同小异,根本上是因为基本数据类型的存储空间不一致。
二、二进制
由计算机的硬件决定,任何存储于计算机中的数据,其本质都是以二进制码存储。
以占用一个字节的byte
和占用两个字节的short
为例,在计算机内存中表示为:
short和byte的在内存中二进制存储方式:
1 Byte = 8bit,其中,最高位表示值正负。
正负值的二进制表示方法:
至于为什么10000000
表示-128而01111111
表示127,涉及到计算机中反码的知识,具体可以看这篇文章原码,反码,补码的深入理解与原理,我们只需要明白:
1、最高位用来表示正负
2、10000000
表示-128而01111111
表示127
3、当最高位为负,值等于取值范围最低值和剩下7位的和相加;最高位为正,则直接取剩下7位的和。
正负值二进制的计算方式:
强制转换过程中,由于占用空间大小不同,冗余的空间将直接舍弃,例如1500ml的水,往1000ml的瓶子里灌,最终只能保存1000ml。
强制转换的二进制表示方式:
如果强制转换时,最后一个字节的最高位为1,则表示为负:
强制转换的二进制负值表示方式:
取值为负的情况捋清了,那丢失精度是怎么回事呢?
其实也是一样的道理:
小数转整数二进制表示方式:
跑一个程序验证一下
public class testCode {
public static void main (String[]args){
int a = 391;
byte b = (byte) a;
System.out.println(b);
}
}
结果: