Java 边界陷阱(边界值的校验)

最近看了一篇博客,博客内容谈到了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 + ";    数据范围: " + "  - ");
	 }
}
  • 运行结果:
    Java 边界陷阱(边界值的校验)_第1张图片
  • 运行结果中的char的数据范围貌似有点问题,不应该是0 - 65535吗?看图:Java 边界陷阱(边界值的校验)_第2张图片
  • Java中的char类型由两个字节即十六位来表示,因为是无符号数,所以为2的16次方,数值范围就为:0 - 2^16-1;

  • 打完,收工!

你可能感兴趣的:(Java)