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(位)80-2^7 - 2^7-1byte b = 10;
short(短整数)160-2^15 - 2^15-1short s = 10;
int(整数)320-2^31 - 2^31-1int i = 10;
long(长整数)640-2^63 - 2^63-1long l = 10L;
float(单精度)320.03.402823e+38 ~ 1.401298e-45float f = 10.0F;
double(双精度)640.01.797693e+308~ 4.9000000e-324double d = 10.0d;
char(字符)160 - 65535
or(\u0000~\uFFFF)
char c = ‘c’;
boolean(布尔值)1falsetrue、falseboolean 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;

  • 打完,收工!
  • 4
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

zhuzicc

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值