数据类型转换
自动转换
一个int类型变量和一个byte类型变量进行加载运算,结果会是什么数据类型呢?
int i = i;
i = i;
byte b = 2;
b = 2;
- 自动转换:将取值范围小的类型自动提升为取值范围大的类型
public static void main(String[] args){
int i = 1;
byte b = 2;
//byte x = b+1; //报错
//int类型和byte类型运算,结果是int类型
int j = b + i;
System.out.println(j);
}
转换原理图解
自动转换按从低到高的顺序转换。不同类型数据间的优先关系如下:
低-------------------------------------------->高
byte,short,char-> int -> long -> float -> double
- 如果两个操作数中有一个是 double类型,另一个操作数就会转换为 double类型。
- 否则,如果其中一个操作数是 float 类型,另一个操作数将会转换为 float类型。
- 否则,如果其中一个操作数是 long 类型,另一个操作数将会转换为 long类型。
- 否则,两个操作数都将被转换为 int 类型
转换规则
运算中,不同类型的数据先转化为同一类型,然后进行运算,转换规则如下:
操作数1类型 | 操作数2类型 | 转换后的类型 |
byte、short、char | int | int |
byte、short、char、int | long | long |
byte、short、char、int、long | float | float |
byte、short、char、int、long、float | double | double |
强制转换
将1.5赋值到int类型变量会发生什么?产生编译失败,肯定无法赋值
int i = 1.5//错误
i = 1.5//错误
double类型占用8个字节,int类型内存占用4个字节。1.5是double类型,取值范围大于int。可以理解为double是8升的水壶,int是4升的水壶,不能把大水壶中的水直接放进小水壶中去。
想要赋值成功,只能通过强制类型转换,将double类型强制转换成int类型才能赋值
- 强制类型转换:将取值范围大的类型强制转换成取值范围小的类型。
比较而言,自动转换是Java自动执行的,而强制转换需要我们自己手动执行
转换格式
数据类型 变量名 = (数据类型)被转换数据值;
//double类型数据强制转换为int类型,直接去掉小数点
int i = (int)1.5;
同样道理,当一个short类型与1相加,我们知道会类型提升,但是还想给结果赋值short类型变量,就需要强制转换
转换原理图解
//将需要转化类型放入格式中
范围小的类型 变量名 = (范围小的类型)范围大的类型;
强烈注意
1、不能对boolean类型进行类型转换
2、不能把对象类型转换成不相关类的对象
3、强制转换一般不推荐使用,因为有可能会发生精度损失,数据溢出
4、浮点数到整数的转换是通过舍弃小数得到的,而不是四舍五入
有趣的转换
1、long强制转成成int类型
int num2 = (int)100L;//1705032704
2、double转换成int,强制类型转换
int num3 = (int)2.99; //3这并不是四舍五入,所有的小数位都会被舍弃掉
char zifu = 'A'//这是一个字符型变量,里面是大写字母A
System.out.println(zifu+1); //66,也就是大写字母A被当做65进行处理
4、byte/short/char三种类型运行的是偶,都会被首先提升为int类型,然后再计算
byte num1 = 40;
byte num2 = 50;
byte result1 = num1+num2;//报错,int从byte转换异常
System.out.println(result1);
//-----------------------------正确写法
byte num1 = 40;
byte num2 = 50;
// byte + byte ———> int +int = int
int result1 = num1+num2;//报错,int从byte转换异常
System.out.println(result1);
5、对于byte/short/char三种类型来说,如果右侧赋值的数值没有超过范围
那么编译器就会自动隐含的补上一个(byte)(short)(char)
public void Notice(){
public static void main(String[]args){
//右侧确实是一个int数字,但是没有超过左侧的范围,就是确定的
//int-->byte,不是自动类型转换
byte num1 = 30;//右侧没有超过左侧的范围
System.out.println(num1);
//byte num2 = 128;//右侧超过了左侧的范围
//int-->char,没有超过范围
//编译器将会自动补上一个隐含的(char)
char zifu = 65;
System.out.println(zifu);
}
}
6、编译器的常量优化
在给变量进行赋值的,如果右侧的表达式当中全都是常亮,没有任何变量,那么编译器javac就会将若干个常亮表达式计算得到结果。
例如:short result = 5+8;//等号右边全都是常亮,没有任何变量参与运算。
编译之后,得到的.class字节码文件当中相当于直接就是short result = 13;
右侧的常亮结果数值,没有超过左侧范围,所以正确。
但是注意的:一旦表示当中有变量参与,那么就不能进行这种优化了
大数值
如果基本的整数和浮点数精度都不能够满足需求,那么可以使用java.math包中的两个类:BigInteger和BigDecimal。这两个类可以处理包含任意航都数字序列的数值。
- BigInteger类实现了任意精度的精度运算
- BigDecimal实现了任意精度的浮点数运算
使用静态的valueOf方法可以将普通的数值转换为大数值
BigInteger a = BigInteger.valuesOf(100);
在运算过程中,使用大数值中的add和multiply方法.
BigInteger c = a.add(b);//相当于c=a+b
BigInteger d = c.multiply(b.add(BigInteger.valueOf(2)));//相当于d=c*(b+2);
API介绍
//API java.math.BigInteger1.1
BigInteger add(BigInteger val);//返回其值为 (this + val) 的 BigInteger
BigInteger subtract(BigInteger val);//返回其值为 (this - val) 的 BigInteger。
BigInteger multiply(BigInteger val);//返回其值为 (this * val) 的 BigInteger。
BigInteger divide(BigInteger val);//返回其值为 (this / val) 的 BigInteger。
int compareTo(BigInteger val);//如果这个大整数与另一个大整数val相等,返回0;如果这个大整数小于另一个大整数val,返回负数;否则,返回正数
//BigDecimal add(BigDecimal augend);//返回一个 BigDecimal,其值为 (this + augend)
//API java.math.BigDecimal
BigDecimal subtract(BigDecimal subtrahend);//返回其值为 (this - val) 的 BigDecimal。
BigDecimal multiply(BigDecimal multiplicand);//返回其值为 (this * val) 的 BigDecimal。
BigDecimal divide(BigDecimal divisor,
RoundingMode roundingMode)//返回其值为 (this / val) 的 BigDecimal。
int compareTo(BigDecimal other);//如果这个大实数与另一个大实数相等,返回 0;如果这个大实数小于另一个大实数,返 回负数;否则,返回正数。
static BigDecimal valueOf(long x);
static BigDecimal valueOf(long x,int scale);//返回值为 x 或 x / 10scale 的一个大实数