题
我写了一个方法,以给定数目的从天转换为毫秒:
private long expireTimeInMilliseconds;
...
public void setExpireTimeInDays(int expireTimeInDays)
{
expireTimeInMilliseconds = expireTimeInDays * 24 * 60 * 60 * 1000;
}
我有一个很难弄清楚我做错了什么。现在我的问题: 是错误如此明显?的
校正的方法,包括:
private long expireTimeInMilliseconds;
...
public void setExpireTimeInDays(int expireTimeInDays)
{
expireTimeInMilliseconds = ((long) expireTimeInDays) * 24 * 60 * 60 * 1000;
}
如果我没有计算前的整数转换为长,我得到一个完整的错误的结果。
解决方案
是明摆着的吗?我想这取决于你一直在使用Java多久,您有多少次处理毫秒。当然,它应该是好的长达24天左右...
我认为最大的提示应该是System.currentTimeMillis()
返回long
。这是一个很好的迹象,在数毫秒内可以得到大。该类型你设置应该是一个很好的提示太多的变量。
当然,你的也的一定要知道,如果你做的整数运算,结果将与环绕在溢出int
。不管是十分明显的或不是可以辩论,但它是一个非常没有意义的讨论。在C#如果关闭溢出检查上,你会发现这个错误很快 - 但当时没有多少开发商这样做(事实上,我不知道,虽然我可能应该)
其他提示
是的,如果你以前做过很明显的。你看到一串数字的任何时间倍增,你应该会自动开始考虑整数溢出错误。在这种情况下你设置溢出如果expireTimeInDays
超过24.从技术上讲,你应该考虑溢出错误的任何你与整数的工作,但是这应该是将它们相乘的一组时间一个非常大的危险信号。
您操作数变量和文字数字是int类型。 int数据类型具有2 ^ 31 -1的最大值。因此,使用如此大量的,INT的数据类型溢出导致表面上的不正确的答案。
在第一个例子中,INT仅提升为长上分配发生的后强>计算的变量。该计算的结果是一个int。
在第二示例中,投射所述第一操作数长,从而导致促进计算为长的。在这种情况下,计算的结果是一个长期的,由于推广。长数据类型不是足够大,你的计算更
您可能有兴趣知道,这是覆盖在“Java的谜题”由Joshua Bloch和尼尔Gafter。
结果 <子>(来源: javapuzzlers.com )子>
您会发现许多其他的Java陷阱,陷阱和角落的情况下在这本书。
我同意谁留下评论的starblue。附加的L的号码。
不,这不是很明显。
但相信我,多了一些多年的实践和修复bug这样以后你成为有关整数溢出很懂事,只是做正确的事情,甚至没有考虑它。
这件事情happend给大家。肯定没有坏码实践中,无知或这样的迹象。
刚要添加到其他的答案,我已发现它在过去有帮助的定义常量(public static final long
)如MILLISECS_DAY
或MILLISECS_HOUR
。
更可读的和有用的。
写这另一种方式是
public void setExpireTimeInDays(int expireTimeInDays)
{
expireTimeInMilliseconds = (long) expireTimeInDays * 24 * 60 * 60 * 1000;
}
或
public void setExpireTimeInDays(int expireTimeInDays)
{
expireTimeInMilliseconds = expireTimeInDays * 24L * 60 * 60 * 1000;
}
如果你对你的代码中使用的FindBugs它会检测这个确切的问题。 “ICAST:转换为长整数乘法的结果。” FindBugs的例子正是你在做什么;以毫秒为单位计算天。
这个问题并不明显,我第一次,我跑了进去。
有一些静态分析工具(FindBugs的),其会发现这些类型的错误。
计算机上的数值的数学可能很难。操作事项顺序可能会影响在你不期望的方式精密度和准确度。日期数学也可以是出奇的棘手。通常最好是使用日期/日历程序,而不是试图自己做数学题,但这些程序都不在Java类库的设计最好的。
我不是想证明我的错误,但是这将是巨大的,如果(一旦计算被分配到long类型的变量)的Java编译器很聪明,促进INT为长计算前
顺便说一句,我用C / C工作++,如果这是一个C程序,我有同样的问题,但在几年前,我一直更加小心这种操作。
我会更加关注下一次(或切换到蟒蛇)...:d