Java 邊界陷阱(邊界值的校驗)

最近看了一篇博客,博客內容談到了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;

  • 打完,收工!
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章