最近看了一篇博客,博客内容谈到了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;
- 打完,收工!