簡體   English   中英

在Java中安全地將long轉換為int

[英]Safely casting long to int in Java

在Java中驗證從longint強制轉換不丟失任何信息的最慣用的方法是什么?

這是我目前的實施:

public static int safeLongToInt(long l) {
    int i = (int)l;
    if ((long)i != l) {
        throw new IllegalArgumentException(l + " cannot be cast to int without changing its value.");
    }
    return i;
}

Java 8添加了一種新方法來實現這一目標。

import static java.lang.Math.toIntExact;

long foo = 10L;
int bar = toIntExact(foo);

如果發生溢出,將拋出ArithmeticException

請參閱: Math.toIntExact(long)

Java 8中添加了其他幾種溢出安全方法。它們以精確結尾。

例子:

  • Math.incrementExact(long)
  • Math.subtractExact(long, long)
  • Math.decrementExact(long)
  • Math.negateExact(long),
  • Math.subtractExact(int, int)

我想我會這樣做:

public static int safeLongToInt(long l) {
    if (l < Integer.MIN_VALUE || l > Integer.MAX_VALUE) {
        throw new IllegalArgumentException
            (l + " cannot be cast to int without changing its value.");
    }
    return (int) l;
}

我認為比重復鑄造更清楚地表達了意圖......但它有點主觀。

注意潛在的興趣 - 在C#中它只是:

return checked ((int) l);

使用Google Guava的Ints類,您的方法可以更改為:

public static int safeLongToInt(long l) {
    return Ints.checkedCast(l);
}

來自鏈接的文檔:

checkedCast時

public static int checkedCast(long value)

如果可能,返回等於value的int值。

參數: value - int類型范圍內的任何值

返回:等於valueint value

拋出: IllegalArgumentException - 如果value大於Integer.MAX_VALUE或小於Integer.MIN_VALUE

順便說一下,你不需要safeLongToInt包裝器,除非你想讓它更改功能而不需要進行大量的重構。

使用BigDecimal:

long aLong = ...;
int anInt = new BigDecimal(aLong).intValueExact(); // throws ArithmeticException
                                                   // if outside bounds

這是一個解決方案,如果你不關心價值,以防它需要更大;)

public static int safeLongToInt(long l) {
    return (int) Math.max(Math.min(Integer.MAX_VALUE, l), Integer.MIN_VALUE);
}

不要:這不是解決方案!

我的第一個方法是:

public int longToInt(long theLongOne) {
  return Long.valueOf(theLongOne).intValue();
}

但這只是將long轉換為int,可能會創建新的Long實例或從Long池中檢索它們。


缺點

  1. 如果數字不在Long的池范圍內,則Long.valueOf會創建一個新的Long實例[-128,127]。

  2. intValue實現intValue事情:

     return (int)value; 

所以這可以被認為比僅僅將longint更糟糕。

我聲稱看到是否更改值的顯而易見的方法是轉換並檢查結果。 但是,我會在比較時刪除不必要的演員表。 我也不太熱衷於一個字母的變量名稱(異常xy ,但不是當它們意味着行和列(有時分別))。

public static int intValue(long value) {
    int valueInt = (int)value;
    if (valueInt != value) {
        throw new IllegalArgumentException(
            "The long value "+value+" is not within range of the int type"
        );
    }
    return valueInt;
}

但是,如果可能的話,我真的想避免這種轉換。 顯然有時它是不可能的,但在那些情況下,就客戶端代碼而言, IllegalArgumentException幾乎肯定是拋出的錯誤異常。

Java整數類型表示為signed。 如果輸入介於2 31和2 32之間 (或-2 31和-2 32 ),則演員會成功,但您的測試將失敗。

什么檢查是所有的高位是否long都是相同的:

public static final long LONG_HIGH_BITS = 0xFFFFFFFF80000000L;
public static int safeLongToInt(long l) {
    if ((l & LONG_HIGH_BITS) == 0 || (l & LONG_HIGH_BITS) == LONG_HIGH_BITS) {
        return (int) l;
    } else {
        throw new IllegalArgumentException("...");
    }
}
(int) (longType + 0)

但龍不能超過最大值:)

另一個解決方案可以是:

public int longToInt(Long longVariable)
{
    try { 
            return Integer.valueOf(longVariable.toString()); 
        } catch(IllegalArgumentException e) { 
               Log.e(e.printstackstrace()); 
        }
}

我已經嘗試過這種情況,客戶端正在進行POST,而服務器數據庫只能理解Integers,而客戶端只有Long。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM