java long 溢出_关于溢出:Java乘法运算行为
我編寫了一種方法,可以將給定的數字從幾天轉換為毫秒:
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;
}
如果在計算之前不將整數轉換為很長的時間,則會得到完全錯誤的結果。
您也可以在常量后面加上L。
人們為什么要關閉它? 似乎是一個可以幫助他人的正當問題。 如果確切重復,請這樣說。
您還可以聲明常量:long 24L * 60L ...
有趣的話題,但我認為這里的實際問題需要更改。"錯誤是否明顯"很容易受到影響。 諸如"為什么即使我的變量為long類型,Java為何也不能將其轉換為long?" 似乎是這里實際討論的內容。
@Outlaw你是對的:" Java為什么不將其轉換為long"在這里比較合適。
明顯嗎?我想這取決于您使用Java已有多長時間,以及必須處理多少次毫秒。當然,最多可以保留24天左右...
我認為最大的提示應該是System.currentTimeMillis()返回long。這很好地表明了毫秒數可能會變大。您要設置的變量的類型也應該是一個很好的提示。
當然,您還必須了解,如果使用int進行算術運算,結果將是int,并在溢出時進行環繞。是否足夠明顯尚有爭議,但這將是毫無意義的討論。在C#中,如果您打開了溢出檢查功能,您會很快發現該錯誤-但是沒有那么多開發人員這樣做(實際上,我可能不會這樣做)。
我期待一個很長的時間,我曾經使用過System.currentTimeMillis()。因為那不是一個新代碼,所以我記不起編寫它時的想法(可能是我期望編譯器提供一些魔術)...
...我認為,就像您所說的那樣,我最大的錯誤是使用int進行算術運算,而沒有注意int溢出。我忘記了基本概念(實際上我沒有為Java學習,但我已經為C / C ++學習)
是的,如果您之前已經做過,那就很明顯了。每當您看到一串數字相乘時,都應該自動開始考慮整數溢出錯誤。在這種情況下,如果expireTimeInDays大于24,則設置為溢出。從技術上講,您應該在處理整數時隨時考慮溢出錯誤,但是像這樣將它們相乘應該是一個很大的危險信號。
您可能想知道Joshua Bloch和Neal Gafter撰寫的" Java Puzzlers"中對此進行了介紹。
(來源:javapuzzlers.com) sub>
您將在本書中發現許多其他的Java陷阱,陷阱和極端案例。
我同意發表評論的繁星點點。在數字后面加上L。
您的操作數變量和文字數字的類型為int。 int數據類型的最大值為2 ^ 31 -1。因此,使用如此大的數字,int的數據類型會溢出,從而導致看似錯誤的答案。
在您的第一個示例中,僅將int賦值給在計算后出現的變量上很長的賦值。計算結果為整數。
第二個示例將第一個操作數強制轉換為long,導致將計算提升為long。在這種情況下,由于提升,計算的結果很長。 long數據類型足以進行計算。
看起來Java具有與C相同的int溢出行為。我想我期望編譯器為我將其轉換(int到long)。它的代碼看起來很簡單(就是這樣)...我只需要更加注意。
不,這不是顯而易見的。
但是請相信我,經過幾年的實踐并修復了此類錯誤之后,您對整數溢出變得非常明智,甚至在做正確的事情時都沒有考慮它。
這件事發生在每個人身上。絕對沒有不良實踐,無知之類的跡象。
有趣的是,我已經編碼了20多年,這是我第一次犯該特定錯誤。當我是C / C ++開發人員時,我曾經注意代碼中的每個小細節。我認為現在我希望編譯器為我做一些"魔術" ...
有一些靜態分析工具(findbug)可以找到這些類型的錯誤。
在計算機上進行數字數學可能很困難。操作順序問題可能會以您意想不到的方式影響精度和準確性。日期數學也可能非常棘手。通常,使用Date / Calendar例程比嘗試自己做數學要好,但是這些例程并不是Java類庫中設計最好的例程。
如果在代碼上使用FindBugs,它將檢測到此確切問題。" ICAST:整數乘法的結果強制轉換為long。" FindBugs的示例正是您在做什么;計算天數(以毫秒為單位)。
第一次遇到這個問題對我來說并不明顯。
另一種寫方法是
public void setExpireTimeInDays(int expireTimeInDays)
{
expireTimeInMilliseconds = (long) expireTimeInDays * 24 * 60 * 60 * 1000;
}
要么
public void setExpireTimeInDays(int expireTimeInDays)
{
expireTimeInMilliseconds = expireTimeInDays * 24L * 60 * 60 * 1000;
}
這樣比較好,我寧愿避免不必要的轉換。謝謝
只是為了增加其他答案,我發現在過去定義常量(public static final long)如MILLISECS_DAY或MILLISECS_HOUR很有幫助。
更具可讀性和實用性。
我并不是想證明我的錯誤,但是如果Java編譯器足夠聰明,可以在計算之前很長一段時間將int提升到很長時間(一旦將計算分配給long類型的變量),那將是很好的選擇
順便說一下,我曾經使用過C / C ++,如果它是C程序,我也會遇到同樣的問題,但是幾年前,我對這種操作更加謹慎。
下次我會更加關注(或切換到python)...:D
總結
以上是生活随笔為你收集整理的java long 溢出_关于溢出:Java乘法运算行为的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: retrofit 会请求两次_Retro
- 下一篇: java中如何检查字符串都是数字_如何在