在 Java 中将 int 转换成 short
1. 概述
使用 Java 时,我们经常会遇到需要转换数据类型以适应特定需求的场景。一种常见的转换是从 int 转换成 short。
本教程中,我们将探讨如何将 int 转换为 short,以及需要注意的潜在陷阱。
2. 问题介绍
Java 提供了几种基本数据类型来存储数值,每种类型都有其范围和精度。例如,int 数据类型是一个 32 位有符号整数,其值范围从 -2 ^ 31 到 2 ^ 31 – 1。另一方面,short 数据类型是一个 16 位有符号整数,可容纳 -2 ^ 15 到 2 ^ 15 – 1 之间的值。
由于 int 的范围比 short 的范围更广,将 int 转换为 short 可能会有潜在的陷阱,我们将在下面的部分中详细讨论。
接下来,让我们探讨一下在 Java 中将 int 转换为 short。
3. 将 int 强制转换成 short
将 int 转换为 short 最简单的方法是强制转换。一个例子可以清楚地说明它是如何工作的:
short expected = 42;
int i = 42;
short result = (short) i;
assertEquals(expected, result);
在 Java 中,整数有两种类型:基元 int 和 Integer。接下来,让我们看看如何将 Integer 实例转换为 short。
4. 使用 Integer.shortValue() 方法
Integer 类提供了 shortValue()
方法。顾名思义,shortValue()
用于将给定的 Integer 转换成 short 值:
short expected = 42;
Integer intObj = 42;
short result = intObj.shortValue();
assertEquals(expected, result);
然而,如果我们看看 shortValue()
方法的实现,就会发现它在内部将 Integer 值强制转换为 short 值:
public short shortValue() {
return (short)value;
}
我们已经注意到,在 Java 中,int 范围大于 short。因此,我们可能会想:如果给定的整数超过了 short 范围,会发生什么?接下来,让我们详细研究一下这一点。
5. 潜在的陷阱
将一个值超过 short 范围的整数强制转换,可能会产生“意外”的结果。接下来,让我们检查几个转换示例:
int oneMillion = 1_000_000;
short result = (short) oneMillion;
assertEquals(16960, result);
本例中,整数值为一百万,超过了 short 的最大值(32767)。强制转换后,它变成了 16960 的 short 值。
此外,如果我们将整数更改为 200 万,我们甚至会得到一个负数(-31616):
int twoMillion = 2_000_000;
result = (short) twoMillion;
assertEquals(-31616, result);
接下来,我们将探讨为什么会出现这些意外的数值。
为了解决这个问题,让我们首先了解在 Java 中,short 是如何表示为二进制数的。
5.1. short: 16 位有符号整数
我们已了解到,short 在 Java 中是一个 16 位有符号整数。最高有效位(MSB)表示整数的符号:0 表示正数,1 表示负数。例如,short 值 42 以这种方式存储:
short 42:
00000000 00101010
^
MSB
按照这个规则,有些人可能会认为 -42 可以表示为 “10000000 00101010”。然而,事实并非如此:
short -42:
11111111 11010110
^
MSB
这是因为 Java 使用 2 的补码来表示负数。简单地说,在二的补码计算中,有两个步骤:首先,将每个位反转,然后将反转的二进制数加一。
接下来,让我们了解一下为什么 -42 可以表示为“1111111111010110”:
Binary : 11111111 11010110 (MSB: 1 -> Negative)
Invert bits : 00000000 00101001
+ 1 : 00000000 00101010
Decimal : 42
Result : -42
现在我们知道了 short 是如何存储的,让我们了解一下如果我们将 int 强制转换为 short 会发生什么。
5.2. 强制转换的工作原理
在 Java 中,int 是一个 32 位有符号整数,比 short 多提供 16 位。因此,当我们将 int 强制转换为 short 时,int 的 16 个高阶位会被截断。
一个例子可以很快阐明这一点。让我们看看当我们将 int 值 42 强制转换为 short 时它是如何工作的:
42 (int) : 00000000 00000000 00000000 00101010
cast to short : 00000000 00101010
Result : 42
现在,我们可以理解为什么当我们将一百万的整数转换为 short 时会得到“意外”的结果。由于 short 的范围比 int 窄,因此在强制转换过程中会丢弃超过 short 容量的高阶位,从而在产生的 short 中产生意外值:
1 million (int) : 00000000 00001111 01000010 01000000
Cast to short : 01000010 01000000
Decimal : 16960
在“强制转换两百万的整数”示例中,我们得到了一个负数,因为截断高阶位后 MSB 为 1:
2 million (int) : 00000000 00011110 10000100 10000000
Cast to short : 10000100 10000000
MSB: 1 -> Negative
Invert bits : 01111011 01111111
+ 1 : 01111011 10000000
Decimal : 31616
Result : -31616
5.3. 创建 intToShort() 函数
将 int 强制转换为 short 时必须谨慎,因为如果 int 值超出 short 的范围,可能会导致数据丢失或意外行为。我们应该始终在强制转换之前,检查 int 值是否在 Short.MIN_VALUE 和 Short.MAX_VALUE 之间:
short intToShort(int i) {
if (i < Short.MIN_VALUE || i > Short.MAX_VALUE) {
throw new IllegalArgumentException("Int is out of short range");
}
return (short) i;
}
然后,当输入整数超出 short 的范围时,它抛出一个异常:
short expected = 42;
int int42 = 42;
assertEquals(expected, intToShort(int42));
int oneMillion = 1_000_000;
assertThrows(IllegalArgumentException.class, () -> intToShort(oneMillion));
6. 结论
本文中,我们探讨了如何在 Java 中将 int 转换为 short,并讨论了转换一个值超出 short 范围的 int 时可能存在的陷阱。