`
welcomezhang
  • 浏览: 17799 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

一个Interger越界引发的线上问题

阅读更多

 

最近有个低级错误,导致线上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,而不是“==”

分享到:
评论

相关推荐

    创建一个IntegerSet(集合类).zip

    本文将深入探讨如何在C++中创建一个名为`IntegerSet`的集合类,以及在这个过程中涉及的关键知识点。 首先,集合类通常用于存储和操作一组特定类型的元素,比如整数。在C++中,我们可以通过定义一个类来实现这个概念...

    义一个整数集合类integerSet。这种类型的对象可以存储10个20~80之间的整数,即他的内部有一个整型数组存储数据。编程:

    - `integerSet(int a[])`: 构造函数接受一个整型数组`a`作为参数,并将该数组赋值给成员变量`c`。 #### 成员方法 1. **判断两个integerSet对象是否相等** - 方法名:`public boolean bool(int b[])` - 功能描述...

    mybatis返回Integer

    int是Java的基本数据类型,它占用32位存储空间,直接存储数值,而Integer是int的包装类,是一个对象,它包含一个int类型的成员变量。在Java中,对象的操作比基本类型复杂,涉及到对象的创建、引用等概念。 MyBatis...

    POJ1503-Integer Inquiry

    综合以上信息,我们可以推测"Integer Inquiry"是一个涉及数值处理或者查询的编程问题,可能需要参赛者利用C++编写程序来处理整数数据,进行特定的查询操作。解题报告会提供问题的解析和算法设计,而源代码则展示了...

    Transform Coding with Integer-to-Integer Transforms.pdf

    这种技术的一个主要优点是进一步减少了熵编码所需的内存需求,同时使用单一共同的标量熵码本对所有组件进行编码。对于高比特率的高斯源编码,这种方法能够在不降低速率失真性能的情况下实现内存需求的减少。 #### ...

    Mybatis Generator将tinyint映射成Integer的解决办法.pdf

    可以创建一个自定义的JavaTypeResolver实现类,如`com.sgy.JavaTypeResolverCustomImpl`,继承自`JavaTypeResolverDefaultImpl`。然后在MyBatis Generator的配置文件中,通过`<javaTypeResolver>`标签指定这个...

    Clock_Integer 指令库应用例程.rar

    在提供的 "Clock_Integer 指令库应用例程.mwp" 文件中,开发者可以看到一个完整的示例,展示了如何在实际项目中使用该库。这个例程可能包括以下步骤: 1. 首先,例程会进行库的初始化,配置所需的硬件定时器和时钟...

    Huge Integer

    1. **数据结构设计**:为了表示大整数,我们可以创建一个动态数组,数组的每个元素代表一个数字位,通常从低位到高位排列。例如,如果数组长度为n,那么数组的元素可以表示从0到n-1位的数字。 2. **初始化和输入**...

    JAVA Integer == equal 比较 doc 比较大小 是否相等

    在 Java 中,Integer 是一个不可变的类,它封装了一个基本类型 int 的值。Integer 对象可以通过自动装箱(autoboxing)或手动创建来获得。自动装箱是指 Java 编译器在编译时将基本类型 int 转换为 Integer 对象的...

    Integer类的使用方法

    在Java编程语言中,`Integer`类是一个非常重要的封装类,它用于将基本数据类型`int`封装成对象。这不仅增强了数据的灵活性,还提供了许多实用的方法来处理整数相关的操作。下面,我们将深入探讨`Integer`类的使用...

    bigdecimal转integer.docx

    在 Java 编程中,`BigDecimal` 和 `Integer` 是两个不同类型的数值表示。`BigDecimal` 用于处理精确的浮点数运算,适合财务或金融计算,因为它可以避免浮点数计算中的精度问题。而 `Integer` 是 Java 中的整数类型,...

    mybatis逆向工具generator,中文注释,Byte改Integer

    在给定的标题中,“mybatis逆向工具generator,中文注释,Byte改Integer”表明这是一个定制版的MyBatis Generator,特别之处在于它对生成的代码进行了修改,将原本自动产生的`Byte`类型字段改为了`Integer`类型。...

    [C++][New]大数Integer类

    由于使用模板,所以只有一个Integer.h头文件 支持如下操作:>, >=, <, , ==, !=, +, +=, -, -=, *, =, /, /=,(输出);支持利用基本整数类型(int,unsigned,long long,……)和字符串(char和std::string)构造类型

    HugeInteger大整数计数器作业

    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 ...

    JAVA-int和Integer的区别

    创建一个`Integer`对象会占用更多内存,因为它包含了一个指向`int`值的引用以及对象本身的开销。由于`Integer`是对象,所以它可以使用面向对象的特性,如方法重载、继承等。`Integer`的范围比`int`大,它可以存储-2^...

    HugeInteger

    创建一个大整数类HugeInteger,该类用一个40个元素的数组来存放一个大整数(最多不超过40位)。 构造函数原型: HugeInteger(String); (1)定义几个大整数算术运算的成员函数,包括input、output、add和sub, add, ...

    JAVA-int和Integer的区别1.zip

    这个特性在处理大量小整数时能提高效率,但也可能导致预期之外的行为,如两个不同的`Integer`引用实际上指向同一个对象。 总之,`int`和`Integer`在Java中各有各的适用场景。如果你需要高效处理大量整数,或者在...

    将 BigDecimal 类型转换为 Integer 类型.pdf

    BigDecimal 类提供了一个名为 `intValue()` 的方法,该方法用于将 BigDecimal 对象转换为 `int` 类型。此方法会返回 BigDecimal 的整数值,前提是该值在 Integer 的取值范围内,即 `-2^31` 到 `2^31 - 1`。例如: ...

    Java8 将List<Integer> 转换成以逗号分割的String字符串

    在Java编程中,将一个`List<Integer>`转换成以逗号分隔的`String`字符串是一种常见的需求,尤其是在处理数据展示或格式化输出时。Java 8引入了新的特性和方法,使得这种转换变得更加简洁和高效。下面我们将深入探讨...

    android数组资源string-array integer-array的用法

    在Android的资源XML文件(通常位于res/values/strings.xml)中,你可以创建一个`string-array`,如下所示: ```xml 字符串1 字符串2 字符串3 ``` `name`属性定义了数组的唯一标识,`item`元素则包含数组中的...

Global site tag (gtag.js) - Google Analytics