2.4java运算需要注意的细节
扩展运算符在进行运算的同时会自动将结果强制转换回左侧变量的类型。
Java 中小于 int
类型的数据在进行算术运算时,会自动提升为 int
类型,这是为了避免溢出问题以及简化指令集。但使用扩展运算符时,其行为有一些特殊之处。扩展运算符在进行运算的同时会自动将结果强制转换回左侧变量的类型。
示例代码
public class ExtendedOperatorConversion {public static void main(String[] args) {// byte 类型使用扩展运算符byte b = 10;b += 5;System.out.println("byte 类型使用 += 后的结果: " + b);// short 类型使用扩展运算符short s = 20;s -= 3;System.out.println("short 类型使用 -= 后的结果: " + s);// char 类型使用扩展运算符char c = 'A';c *= 2;System.out.println("char 类型使用 *= 后的结果: " + c);// 普通运算符与扩展运算符对比byte normalByte = 10;// 普通加法运算,需要显式强制类型转换normalByte = (byte) (normalByte + 5);System.out.println("byte 类型使用普通 + 并强制转换后的结果: " + normalByte);}
}
代码解释
byte
类型使用扩展运算符:b += 5
等价于b = (byte)(b + 5)
。在运算时,b
先被提升为int
类型进行b + 5
的运算,得到一个int
类型的结果,然后扩展运算符会自动将结果强制转换回byte
类型再赋值给b
。
short
类型使用扩展运算符:s -= 3
等价于s = (short)(s - 3)
。同样,s
先提升为int
类型运算,结果再强制转换回short
类型赋值给s
。
char
类型使用扩展运算符:c *= 2
等价于c = (char)(c * 2)
。c
提升为int
类型进行乘法运算,结果强制转换回char
类型赋值给c
。
- 普通运算符与扩展运算符对比:
- 使用普通运算符(如
+
)进行运算时,由于运算结果是int
类型,若要赋值给小于int
类型的变量,需要显式地进行强制类型转换,如normalByte = (byte) (normalByte + 5)
。
- 使用普通运算符(如
注意事项
- 数据溢出风险:由于扩展运算符会自动进行强制类型转换,当运算结果超出左侧变量类型的取值范围时,会发生数据溢出。例如:
byte overflowByte = 120;
overflowByte += 10;
System.out.println("发生溢出的 byte 结果: " + overflowByte);
这里 120 + 10
的结果超出了 byte
类型的范围(-128 到 127),强制转换后会得到一个溢出的结果。
- 代码可读性:虽然扩展运算符使用起来更简洁,但要清楚其背后的自动类型转换机制,避免因疏忽导致数据错误。在复杂运算场景中,显式的类型转换和普通运算符的使用可能会让代码更易理解
当进行整数运算时,其结果会是整数,小数部分会被直接舍去
原理
Java 中有多种整数类型,像 byte
、short
、int
、long
等。当使用这些整数类型进行运算时,Java 会按照整数的规则处理结果。由于整数类型无法存储小数部分,所以在运算结果为小数时,会直接舍弃小数部分,只保留整数部分,这种处理方式也被叫做截断取整。
示例代码
以下示例代码展示了不同整数运算中小数部分被舍去的情况:
public class IntegerArithmetic {public static void main(String[] args) {// 示例 1: 整数除法int dividend = 10;int divisor = 3;int result1 = dividend / divisor;System.out.println("10 除以 3 的整数运算结果: " + result1);// 示例 2: 多个整数运算int num1 = 20;int num2 = 7;int num3 = 4;int result2 = (num1 + num2) / num3;System.out.println("(20 + 7) 除以 4 的整数运算结果: " + result2);// 示例 3: 不同整数类型的运算long longNum = 100L;int intNum = 3;long result3 = longNum / intNum;System.out.println("100L 除以 3 的整数运算结果: " + result3);}
}
代码解释
- 整数除法:在
10 / 3
这个运算里,数学上的结果是3.333...
,但因为是整数运算,小数部分被舍去,最终结果为3
。 - 多个整数运算:先计算
20 + 7
得到27
,再进行27 / 4
的运算,数学结果是6.75
,舍去小数部分后结果为6
。 - 不同整数类型的运算:当
long
类型和int
类型进行运算时,结果会自动提升为long
类型,但同样会舍去小数部分。100L / 3
的数学结果是33.333...
,最终结果为33
。
注意事项和其他情况
若要得到精确的小数结果,可以把参与运算的操作数至少一个转换为浮点数类型(如 float
或 double
)。示例如下:
public class IntegerToFloatArithmetic {public static void main(String[] args) {int dividend = 10;int divisor = 3;double result = (double) dividend / divisor;System.out.println("10 除以 3 的精确结果: " + result);}
}
在上述代码中,将 dividend
强制转换为 double
类型,这样运算时就会按照浮点数的规则进行,得到的结果就是精确的小数 3.333...
。在 Java 整数运算中,要时刻留意结果会舍去小数部分这一特性,依据具体需求选择合适的数据类型和运算方式
浮点数类型(float
和 double
)在进行运算时会存在不精确性的问题
原因
计算机在存储和处理浮点数时,采用的是二进制表示法。然而,大多数十进制小数无法精确地用二进制表示,这就导致了浮点数在存储和运算过程中会出现精度损失。
以十进制小数 0.1
为例,它在二进制中是一个无限循环小数。由于计算机的存储空间有限,只能对其进行近似表示,这就使得在进行浮点数运算时,结果可能会出现微小的误差。
示例代码
public class FloatingPointPrecision {public static void main(String[] args) {// 示例 1: 简单的加法运算double num1 = 0.1;double num2 = 0.2;double result = num1 + num2;System.out.println("0.1 + 0.2 的结果: " + result);// 预期结果是 0.3,但实际输出可能不是精确的 0.3// 示例 2: 比较运算if (result == 0.3) {System.out.println("结果等于 0.3");} else {System.out.println("结果不等于 0.3");}}
}
代码解释
- 加法运算:在上述代码中,
0.1
和0.2
相加的预期结果是0.3
,但由于浮点数的不精确性,实际输出的结果可能是一个接近0.3
的值,如0.30000000000000004
。 - 比较运算:由于
result
的值不是精确的0.3
,所以在进行result == 0.3
的比较时,结果为false
。
解决方案
为了避免浮点数运算的不精确性问题,可以使用 java.math.BigDecimal
类。BigDecimal
类可以精确地表示和处理任意精度的十进制数。
import java.math.BigDecimal;public class BigDecimalExample {public static void main(String[] args) {// 创建 BigDecimal 对象BigDecimal bd1 = new BigDecimal("0.1");BigDecimal bd2 = new BigDecimal("0.2");// 进行加法运算BigDecimal sum = bd1.add(bd2);System.out.println("0.1 + 0.2 的精确结果: " + sum);// 比较运算BigDecimal expected = new BigDecimal("0.3");if (sum.compareTo(expected) == 0) {System.out.println("结果等于 0.3");} else {System.out.println("结果不等于 0.3");}}
}
- 创建
BigDecimal
对象:使用字符串构造函数创建BigDecimal
对象,这样可以避免浮点数的不精确性。 - 加法运算:使用
add()
方法进行加法运算,得到精确的结果。 - 比较运算:使用
compareTo()
方法进行比较,该方法返回0
表示相等,返回负数表示小于,返回正数表示大于。
在需要精确计算的场景中,如金融领域,建议使用 BigDecimal
类来避免浮点数运算的不精确性问题。