最近有个低级错误,导致线上bug。情况是这样的:
业务需求
需要写一个方法,判断createTime在60天以内的记录才有效,才有资格进行后续的抽奖操作。
实现
private boolean drawTimeExpired(Date createTime) { if (createTime == null) { errorLogger.error(genErrorInfo(IMPOSSIBLE_CONDITION, "createTime null", "drawTimeExpired")); return false; } return new DateTime().getMillis() > createTime.getTime() + 60 * 24 * 3600 * 1000; }
这样写有问题么?
——乍一看,没毛病啊。
60天*24小时*60分*60s*1000ms
测试一下
用1天和61天分别测试一下看看
public static void main(String[] args) throws Exception{ DateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); Date createTime = sdf.parse("2017-04-09 13:14:15"); System.out.println(new DateTime().getMillis() > createTime.getTime() + 60 * 24 * 3600 * 1000); //false Date createTime2 = sdf.parse("2017-02-08 13:14:15"); System.out.println(new DateTime().getMillis() > createTime2.getTime() + 60 * 24 * 3600 * 1000); //true }
看结果,还是没毛病啊~
再用15天测试一下
public static void main(String[] args) throws Exception{ DateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); Date createTime3 = sdf.parse("2017-03-25 13:14:15"); System.out.println(new DateTime().getMillis() > createTime3.getTime() + 60 * 24 * 3600 * 1000); }
结果是true。
咦!这咋回事,3月25号肯定没超过60天啊,颠覆世界观了?
再仔细debug一下,发现了问题所在
System.out.println(60 * 24 * 3600 * 1000);//889032704 System.out.println(60 * 24 * 3600 * 1000L);//5184000000
这是咋回事呢?
整数越界了,60天的毫秒数吵过了整数的最大值。
那我们来看一下 java各数据类型的取值范围:
public static void main(String[] args) throws Exception{ System.out.println("Integer.MIN_VALUE = " + Integer.MIN_VALUE); System.out.println("Integer.MAX_VALUE = " + Integer.MAX_VALUE); System.out.println("Long.MIN_VALUE = " + Long.MIN_VALUE); System.out.println("Long.MAX_VALUE = " + Long.MAX_VALUE); System.out.println("Float.MIN_VALUE = " + Float.MIN_VALUE); System.out.println("Float.MIN_NORMAL = " + Float.MIN_NORMAL); System.out.println("Float.MAX_VALUE = " + Float.MAX_VALUE); System.out.println("Double.MAX_VALUE = " + Double.MAX_VALUE); System.out.println("Double.MIN_VALUE = " + Double.MIN_VALUE); }
结果如下:
Integer.MIN_VALUE = -2147483648 Integer.MAX_VALUE = 2147483647 Long.MIN_VALUE = -9223372036854775808 Long.MAX_VALUE = 9223372036854775807 Float.MIN_VALUE = 1.4E-45 Float.MIN_NORMAL = 1.17549435E-38 Float.MAX_VALUE = 3.4028235E38 Double.MAX_VALUE = 1.7976931348623157E308 Double.MIN_VALUE = 4.9E-324
整数最大值为:2147483647
2147483647/24/3600/1000=24.85..天
fix措施
1.25天以内可以用Interger
2.求天数的毫秒数这种情况一律用范围更广的Long类型来表示。
fix后的代码:
private boolean drawTimeExpired(Date createTime) { if (createTime == null) { errorLogger.error(genErrorInfo(IMPOSSIBLE_CONDITION, "createTime null", "drawTimeExpired")); return false; } return new DateTime().getMillis() > createTime.getTime() + 60 * 24 * 3600 * 1000L; }
看出来了么?只加了一个L。
小结
有时候一个好的编程习惯会帮你规避一些容易范的小错。
比如大数切记用Long,而不需要死记各类型的取值范围
比如相等比较用equals,而不是“==”
相关推荐
本文将深入探讨如何在C++中创建一个名为`IntegerSet`的集合类,以及在这个过程中涉及的关键知识点。 首先,集合类通常用于存储和操作一组特定类型的元素,比如整数。在C++中,我们可以通过定义一个类来实现这个概念...
- `integerSet(int a[])`: 构造函数接受一个整型数组`a`作为参数,并将该数组赋值给成员变量`c`。 #### 成员方法 1. **判断两个integerSet对象是否相等** - 方法名:`public boolean bool(int b[])` - 功能描述...
int是Java的基本数据类型,它占用32位存储空间,直接存储数值,而Integer是int的包装类,是一个对象,它包含一个int类型的成员变量。在Java中,对象的操作比基本类型复杂,涉及到对象的创建、引用等概念。 MyBatis...
综合以上信息,我们可以推测"Integer Inquiry"是一个涉及数值处理或者查询的编程问题,可能需要参赛者利用C++编写程序来处理整数数据,进行特定的查询操作。解题报告会提供问题的解析和算法设计,而源代码则展示了...
这种技术的一个主要优点是进一步减少了熵编码所需的内存需求,同时使用单一共同的标量熵码本对所有组件进行编码。对于高比特率的高斯源编码,这种方法能够在不降低速率失真性能的情况下实现内存需求的减少。 #### ...
可以创建一个自定义的JavaTypeResolver实现类,如`com.sgy.JavaTypeResolverCustomImpl`,继承自`JavaTypeResolverDefaultImpl`。然后在MyBatis Generator的配置文件中,通过`<javaTypeResolver>`标签指定这个...
在提供的 "Clock_Integer 指令库应用例程.mwp" 文件中,开发者可以看到一个完整的示例,展示了如何在实际项目中使用该库。这个例程可能包括以下步骤: 1. 首先,例程会进行库的初始化,配置所需的硬件定时器和时钟...
1. **数据结构设计**:为了表示大整数,我们可以创建一个动态数组,数组的每个元素代表一个数字位,通常从低位到高位排列。例如,如果数组长度为n,那么数组的元素可以表示从0到n-1位的数字。 2. **初始化和输入**...
在 Java 中,Integer 是一个不可变的类,它封装了一个基本类型 int 的值。Integer 对象可以通过自动装箱(autoboxing)或手动创建来获得。自动装箱是指 Java 编译器在编译时将基本类型 int 转换为 Integer 对象的...
在Java编程语言中,`Integer`类是一个非常重要的封装类,它用于将基本数据类型`int`封装成对象。这不仅增强了数据的灵活性,还提供了许多实用的方法来处理整数相关的操作。下面,我们将深入探讨`Integer`类的使用...
在 Java 编程中,`BigDecimal` 和 `Integer` 是两个不同类型的数值表示。`BigDecimal` 用于处理精确的浮点数运算,适合财务或金融计算,因为它可以避免浮点数计算中的精度问题。而 `Integer` 是 Java 中的整数类型,...
在给定的标题中,“mybatis逆向工具generator,中文注释,Byte改Integer”表明这是一个定制版的MyBatis Generator,特别之处在于它对生成的代码进行了修改,将原本自动产生的`Byte`类型字段改为了`Integer`类型。...
由于使用模板,所以只有一个Integer.h头文件 支持如下操作:>, >=, <, , ==, !=, +, +=, -, -=, *, =, /, /=,(输出);支持利用基本整数类型(int,unsigned,long long,……)和字符串(char和std::string)构造类型
HugeInteger Class) Create a class HugeInteger that uses a 40-element array of digits to store integers as large as 40 digits each. Provide member functions input, output, add and subtract. For ...
创建一个`Integer`对象会占用更多内存,因为它包含了一个指向`int`值的引用以及对象本身的开销。由于`Integer`是对象,所以它可以使用面向对象的特性,如方法重载、继承等。`Integer`的范围比`int`大,它可以存储-2^...
创建一个大整数类HugeInteger,该类用一个40个元素的数组来存放一个大整数(最多不超过40位)。 构造函数原型: HugeInteger(String); (1)定义几个大整数算术运算的成员函数,包括input、output、add和sub, add, ...
这个特性在处理大量小整数时能提高效率,但也可能导致预期之外的行为,如两个不同的`Integer`引用实际上指向同一个对象。 总之,`int`和`Integer`在Java中各有各的适用场景。如果你需要高效处理大量整数,或者在...
BigDecimal 类提供了一个名为 `intValue()` 的方法,该方法用于将 BigDecimal 对象转换为 `int` 类型。此方法会返回 BigDecimal 的整数值,前提是该值在 Integer 的取值范围内,即 `-2^31` 到 `2^31 - 1`。例如: ...
在Java编程中,将一个`List<Integer>`转换成以逗号分隔的`String`字符串是一种常见的需求,尤其是在处理数据展示或格式化输出时。Java 8引入了新的特性和方法,使得这种转换变得更加简洁和高效。下面我们将深入探讨...
在Android的资源XML文件(通常位于res/values/strings.xml)中,你可以创建一个`string-array`,如下所示: ```xml 字符串1 字符串2 字符串3 ``` `name`属性定义了数组的唯一标识,`item`元素则包含数组中的...