java - सुरक्षित रूप से जावा में int करने के लिए लंबे समय तक कास्टिंग




casting (7)

जावा में सबसे बेवकूफ तरीका क्या है यह सत्यापित करने के लिए कि long से int long कास्ट किसी भी जानकारी को खो नहीं देता है?

यह मेरा वर्तमान कार्यान्वयन है:

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;
}

BigDecimal के साथ:

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

Google Guava's Ints क्लास के साथ, आपकी विधि को बदला जा सकता है:

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

लिंक किए गए दस्तावेज़ों से:

checkedCast

public static int checkedCast(long value)

यदि संभव हो तो value बराबर int मान देता है।

पैरामीटर: value - int प्रकार की सीमा में कोई भी मान

रिटर्न: int मान जो value बराबर है

फेंकता है: IllegalArgumentException - यदि value Integer.MAX_VALUE से अधिक है या Integer.MAX_VALUE से कम है

संयोग से, आपको safeLongToInt आवश्यकता नहीं है, जब तक कि आप पाठ्यक्रम के व्यापक रिफैक्टरिंग के बिना कार्यक्षमता को बदलने के लिए इसे जगह में छोड़ना नहीं चाहते हैं।


ऐसा करने के लिए जावा 8 के साथ एक नई विधि जोड़ा गया है।

import static java.lang.Math.toIntExact;

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

अतिप्रवाह के मामले में एक अंकगणितीय अपवाद फेंक देगा।

देखें: Math.toIntExact(long)

जावा 8 में कई अन्य अतिप्रवाह सुरक्षित विधियों को जोड़ा गया है। वे सटीक रूप से समाप्त होते हैं।

उदाहरण:

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

जावा पूर्णांक प्रकारों को हस्ताक्षरित के रूप में दर्शाया गया है। 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("...");
    }
}

मैं दावा करता हूं कि यह देखने का स्पष्ट तरीका है कि मूल्य को कास्ट करना है या नहीं, मूल्य को कास्ट करना और परिणाम की जांच करना होगा। हालांकि, तुलना करते समय मैं अनावश्यक कलाकारों को हटा दूंगा। मैं एक अक्षर चर नामों (अपवाद x और y , पर भी बहुत उत्सुक नहीं हूं, लेकिन जब उनका मतलब पंक्ति और स्तंभ (कभी-कभी क्रमशः) होता है)।

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 अपवाद लगभग निश्चित रूप से गलत कोड अपवाद है जहां तक ​​क्लाइंट कोड का संबंध है।


यहां एक समाधान है, यदि आप मूल्य के बारे में परवाह नहीं करते हैं तो यह आवश्यक है तो आवश्यक है;)

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

(int) (longType + 0)

लेकिन लंबे समय तक अधिकतम नहीं हो सकता :)





casting