如题,一起来看个例子:
public static void main(String[] args) {
System.out.println("The result of Integer type is:" + Math.abs(Integer.MIN_VALUE));
System.out.println("The result of Long type is:" + Math.abs(Long.MIN_VALUE));
System.out.println("The result of Byte type is:" + Math.abs(Byte.MIN_VALUE));
}
看下结果喽:
The result of Integer type is:-2147483648
The result of Long type is:-9223372036854775808
The result of Byte type is:128
咦?第三个看似是正确的,但是前两个究竟是怎么一回事?明明是绝对值,怎么可能是负数呢?让我们一起来看下abs的方法源码:
public static long abs(long a) {
return (a < 0) ? -a : a;
}
so easy的代码,如果是是负数,直接求相反数,如果是非负数,直接取原值。那么问题就转换为了求相反数的问题了。
我们知道,计算机只存储补码,因为计算机只会做加法,而原码和反码的加法运算都会有问题的(具体可参考计算机原理相关知识)。求一个数的相反数就是对其补码连同符号位求反然后加1。好,了解这些基础知识,我们一起来看下为何最小值的相反数是其自身。如果一个数占8位,则其最小值的补码为10000000,老实说,这个数其实就是-0,但0只有一个就够了,索性定规矩的人就把这个值作为最小值-128了。试着按照求相反数的公式,将这个值按位求反,然后加一,发现还是原值。所以前两个类型就很好解释了。
but,第三种是个什么情况,为什么不是自身呢?这个要看Math.abs了,其入参为byte时,实际调用时传入的形参为int,因为byte类型可以自动转换为int类型的,具体原因我还没找到,不信看下面这个代码。
public static void main(String[] args) {
byte value = 8;
test(value);
}
private static void test(int param) {
System.out.println("调用成功:" + param);
}
如果你运行一下,会发现这个代码是可以运行的,所以,即使我们将byte类型传给Math.abs,他还是拿int类型来处理的。int位数比这个多。
而且,Byte.MIN_VALUE默认就是int类型的,只不过其将值赋给了byte类型的,如果我们真的用byte类型来操作。会发现结果跟预期的是一样的,不信的话请看:
class Scratch {
public static void main(String[] args) {
System.out.println("The result of Byte type is:" + (-(ByteTest.MIN_VALUE)));
}
}
class ByteTest {
public static final byte MIN_VALUE = 0b1000000;
}
看结果:
The result of Byte type is:-64
可知,真实的byte类型的操作是符合求反的原理的。
此外,如果在byte类型中,将byte类型的位数设为8,则其自动会转化为Int类型,不信的话,你试试,看看idea会不会报错呢?