数据范围
int(整数): 32位,范围是-2,147,483,648到2,147,483,647(约 ±21亿)。short(短整型): 16位,范围是-32,768到32,767。
short 的范围比 int 小得多,当将一个 int 值赋给 short 变量时,Java 编译器会进行检查。int 的值超出了 short 的表示范围,编译器会报错,因为它知道这会导致数据丢失。

直接赋值(需要显式类型转换)
int 的值在 short 的范围内,可以直接赋值,但必须使用强制类型转换(cast),告诉编译器你明确知道自己在做什么,并愿意承担潜在的风险。
public class IntToShortExample {
public static void main(String[] args) {
int intValue1 = 100;
short shortValue1;
// 情况1:int的值在short的范围内,可以成功转换
// 必须使用 (short) 进行强制转换
shortValue1 = (short) intValue1;
System.out.println("转换成功: " + intValue1 + " -> " + shortValue1);
int intValue2 = 32767; // short的最大值
short shortValue2 = (short) intValue2;
System.out.println("转换成功: " + intValue2 + " -> " + shortValue2);
int intValue3 = -32768; // short的最小值
short shortValue3 = (short) intValue3;
System.out.println("转换成功: " + intValue3 + " -> " + shortValue3);
}
}
输出:
转换成功: 100 -> 100
转换成功: 32767 -> 32767
转换成功: -32768 -> -32768
超出范围的转换(精度丢失)
int 的值超出了 short 的范围,强制转换依然可以编译通过,但会发生“回绕”(wrap-around)或“截断”(truncation)现象,高位(多余的16位)会被直接丢弃,只保留低16位,这会导致结果变得完全不可预测。
public class IntToShortOverflowExample {
public static void main(String[] args) {
int intValue1 = 32768; // short的最大值 + 1
short shortValue1 = (short) intValue1;
// 32768 的二进制是 0000 0000 0000 0000 1000 0000 0000 0000
// 只保留低16位: 1000 0000 0000 0000,这表示 -32768
System.out.println("溢出转换: " + intValue1 + " -> " + shortValue1);
int intValue2 = 65535; // 2^16 - 1
short shortValue2 = (short) intValue2;
// 65535 的二进制是 0000 0000 0000 0000 1111 1111 1111 1111
// 只保留低16位: 1111 1111 1111 1111,这表示 -1
System.out.println("溢出转换: " + intValue2 + " -> " + shortValue2);
int intValue3 = -32769; // short的最小值 - 1
short shortValue3 = (short) intValue3;
// -32769 的二进制补码是 1111 1111 1111 1111 1000 0000 0000 0001
// 只保留低16位: 1000 0000 0000 0001,这表示 32767
System.out.println("下溢转换: " + intValue3 + " -> " + shortValue3);
}
}
输出:

溢出转换: 32768 -> -32768
溢出转换: 65535 -> -1
下溢转换: -32769 -> 32767
注意:这种“回绕”行为在某些底层编程(如游戏开发、图形学)中是有意为之的,但在大多数业务逻辑中,它是一个严重的 Bug。
编译时错误
如果在不进行强制转换的情况下直接赋值,并且值可能超出范围,编译器会直接报错。
public class IntToShortCompileError {
public static void main(String[] args) {
int largeInt = 50000;
short myShort;
// 下面这行代码会编译失败!
// 错误信息: incompatible types: possible lossy conversion from int to short
// myShort = largeInt;
// 必须加上强制转换才能通过编译
myShort = (short) largeInt;
System.out.println("通过强制转换: " + myShort);
}
}
编译错误:
IntToShortCompileError.java:8: 错误: 不兼容的类型: 从 int 转换到 short 可能会有损失
myShort = largeInt;
^
1 个错误
使用 Math.toIntExact() 进行安全转换 (Java 8+)
如果你想在转换前检查 int 的值是否在 short 范围内,并且如果不在就抛出一个异常,而不是静默地丢失数据,可以自己编写一个检查方法,或者使用 Math 类中的工具。
public class SafeIntToShortConversion {
public static void main(String[] args) {
int intValue = 100;
// 安全转换方法
short shortValue = safeIntToShort(intValue);
System.out.println("安全转换成功: " + shortValue);
int outOfRangeValue = 50000;
try {
safeIntToShort(outOfRangeValue);
} catch (ArithmeticException e) {
System.out.println("捕获到异常: " + e.getMessage());
}
}
/**
* 安全地将 int 转换为 short,如果超出范围则抛出异常。
* @param value 要转换的 int 值
* @return 转换后的 short 值
* @throws ArithmeticException value 超出 short 范围
*/
public static short safeIntToShort(int value) {
if (value < Short.MIN_VALUE || value > Short.MAX_VALUE) {
throw new ArithmeticException("Integer value " + value + " is out of range for a short");
}
return (short) value;
}
}
输出:
安全转换成功: 100
捕获到异常: Integer value 50000 is out of range for a short
总结与最佳实践
| 场景 | 方法 | 描述 | 风险 |
|---|---|---|---|
| 已知值在范围内 | (short) myInt |
使用强制类型转换。 | 无风险。 |
| 值可能超出范围 | 先检查,再转换 | if (myInt >= Short.MIN_VALUE && myInt <= Short.MAX_VALUE) { ... } |
推荐做法,可以避免静默的数据丢失,使 Bug 更容易被发现。 |
| 不关心数据丢失 | (short) myInt |
直接强制转换。 | 高风险。myInt 超出范围,结果将是错误的,但程序不会报错。 |
| 明确想在下溢/溢出时抛出异常 | safeIntToShort(myInt) |
自定义方法,先检查范围,再转换,失败则抛出 ArithmeticException。 |
最安全,适用于需要严格数据校验的场景。 |
核心建议:永远不要盲目地进行 (short) int 转换,在转换前,你应该清楚地知道 int 变量的值是否在 short 的合法范围内,如果不确定,务必先进行检查。
