最近看了一篇博客,博客內容談到了Java基本數據類型邊界值的問題,細細品味後覺得值得記錄一下。
一、案列
某商家生產的電子產品非常暢銷,需要提前30天預訂才能搶到手,同時還規定了一個會員可擁有的最多產品數量,目的是爲了防止囤積壓貨肆意加價。會員的預訂過程是這樣的:先登錄官方網站,選擇產品型號,然後設置需要預訂的數量,提交,符合規則即提示下單成功,不符合規則提示下單失敗,後臺的處理模擬如下:
import java.util.Scanner;
public class Demo {
// 一個會員擁有產品的最多數量
public final static int LIMIT = 2000;
public static void main(String[] args) {
// 會員當前用有的產品數量
int cur = 1000;
Scanner input = new Scanner(System.in);
System.out.println("請輸入需要預定的數量:");
while (input.hasNextInt()) {
int order = input.nextInt();
if (order > 0 && order + cur <= LIMIT) {
System.out.println("你已經成功預定:" + order + " 個產品");
} else {
System.out.println("超過限額,預定失敗!");
}
}
}
}
- 以上是一個簡單的訂單處理程序demo示例,來看一下代碼運行結果:
- 結果看上去是沒有問題,代碼也很簡單,看一眼就知道是什麼意思,來我們接着再試一次:
- 竟然成功了,不可思議,輸入的數字2147483647已經遠超出用戶限額2000,但是爲什麼會成功呢?仔細看 order + cur <= LIMIT 這裏的數據類型是int,而示例輸入的數字2147483647正好是int類型的邊界值(max),2147483647 + 1000 = -2147482649,小於限定條件LIMIT,所以導致錯誤的發生。
- 在單元測試中,有一項測試叫做邊界測試(也叫臨界測試),如果一個方法接收的是int類型的參數,那麼以下三個值是必須測試的:0、正最大、負最小,其中正最大、負最小是邊界值,如果這三個值都沒有問題,方法纔是比較安全可靠的。我們的例子就是因爲缺少邊界測試,致使生產系統產生了嚴重的偏差。
二、解決邊界問題
- 對加減後的值進行條件判斷;
public static void main(String[] args) {
// 會員當前用有的產品數量
int cur = 1000;
Scanner input = new Scanner(System.in);
System.out.println("請輸入需要預定的數量:");
while (input.hasNextInt()) {
int order = input.nextInt();
// 對加減後的值進行條件判斷,考慮邊界問題
int totalNum = order + cur;
System.out.println(totalNum);
if (order > 0 && totalNum > 0 && totalNum <= LIMIT) {
System.out.println("你已經成功預定:" + order + " 個產品");
} else {
System.out.println("超過限額,預定失敗!");
}
}
}
- 運行結果:
三、複習Java基本數據類型
- 既然說到基本數據類型,就來順便回顧一下Java中的4類8種基本數據類型:
數據類型 | 二進制位數 | 默認值 | 取值範圍 | 示例 |
---|---|---|---|---|
byte(位) | 8 | 0 | -2^7 - 2^7-1 | byte b = 10; |
short(短整數) | 16 | 0 | -2^15 - 2^15-1 | short s = 10; |
int(整數) | 32 | 0 | -2^31 - 2^31-1 | int i = 10; |
long(長整數) | 64 | 0 | -2^63 - 2^63-1 | long l = 10L; |
float(單精度) | 32 | 0.0 | 3.402823e+38 ~ 1.401298e-45 | float f = 10.0F; |
double(雙精度) | 64 | 0.0 | 1.797693e+308~ 4.9000000e-324 | double d = 10.0d; |
char(字符) | 16 | 空 | 0 - 65535 or(\u0000~\uFFFF) |
char c = ‘c’; |
boolean(布爾值) | 1 | false | true、false | boolean b = true; |
- 代碼示例:
public class Test {
static byte b;
static short s;
static int i;
static long l;
static float f;
static double d;
static char c;
static boolean bo;
public static void main(String[] args) {
System.out.println("byte的大小 : " + Byte.SIZE+ "; 默認值:" + b + "; 數據範圍:" + Byte.MIN_VALUE + " - " + Byte.MAX_VALUE);
System.out.println("short的大小 :" + Short.SIZE + "; 默認值:" + s + "; 數據範圍:" + Short.MIN_VALUE + " - " + Short.MAX_VALUE);
System.out.println("int的大小 :" + Integer.SIZE + "; 默認值:" + i + "; 數據範圍:" + Integer.MIN_VALUE + " - " + Integer.MAX_VALUE);
System.out.println("long的大小 :" + Long.SIZE + "; 默認值:" + l + "; 數據範圍:" + Long.MIN_VALUE + " - " + Long.MAX_VALUE);
System.out.println("float的大小 :" + Float.SIZE + "; 默認值:" + f + "; 數據範圍:" + Float.MIN_VALUE + " - " + Float.MAX_VALUE);
System.out.println("double的大小 :" + Double.SIZE + "; 默認值:" + d + "; 數據範圍:" + Double.MIN_VALUE + " - " + Double.MAX_VALUE);
System.out.println("char的大小 :" + Character.SIZE + "; 默認值:" + c + "; 數據範圍:" + Character.MIN_VALUE + " - " + Character.MAX_VALUE);
System.out.println("boolean的大小:" + " ; 默認值:" + bo + "; 數據範圍: " + " - ");
}
}
- 運行結果:
- 運行結果中的char的數據範圍貌似有點問題,不應該是0 - 65535嗎?看圖:
- Java中的char類型由兩個字節即十六位來表示,因爲是無符號數,所以爲2的16次方,數值範圍就爲:0 - 2^16-1;
- 打完,收工!