Какой самый идиоматичный способ в Java проверить, что приведение от long
к int
не теряет никакой информации?
Это моя текущая реализация:
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, чтобы сделать это.
Выкинет
ArithmeticException
в случае переполнения.Видеть:
Math.toIntExact(long)
Несколько других безопасных методов переполнения были добавлены в Java 8. Они заканчиваются точным .
Примеры:
Math.incrementExact(long)
Math.subtractExact(long, long)
Math.decrementExact(long)
Math.negateExact(long),
Math.subtractExact(int, int)
источник
addExact
иmultiplyExact
. Следует отметить, что Division (MIN_VALUE/-1
) и абсолютное значение (abs(MIN_VALUE)
) не имеют безопасных методов удобства.Math.toIntExact()
вместо обычного приведенияint
? РеализацияMath.toIntExact()
просто бросаетlong
вint
.Я думаю, я бы сделал это так же просто, как:
Я думаю, что это выражает намерение более четко, чем повторное приведение ... но это несколько субъективно.
Примечание потенциального интереса - в C # это будет просто:
источник
(!(Integer.MIN_VALUE <= l && l <= Integer.MAX_VALUE))
. Мне трудно обдумать другие способы сделать это. Жалкой Явы нетуunless
.int
.С помощью класса Ints Google Guava ваш метод может быть изменен на:
Из связанных документов:
Между прочим, вам не нужна
safeLongToInt
обертка, если вы не хотите оставить ее на месте для изменения функциональности без большого рефакторинга, конечно.источник
Ints.checkedCast
делает именно то, что делает OPInts.checkedCast(l)
напрямую.Ints.saturatedCast
который будет возвращать ближайшее значение, а не выбрасывать исключение.С BigDecimal:
источник
BigDecimal.valueOf(aLong)
вместоnew BigDecimal(aLong)
обозначения, что новый экземпляр не требуется. То, выполняет ли среда выполнения кэширование в этом методе, зависит от конкретной реализации, как и возможное присутствие Escape Analysis. В большинстве случаев это не влияет на производительность.вот решение, в случае, если вы не заботитесь о стоимости, если она больше, чем нужно;)
источник
too low
? Пожалуйста, предоставьте пример использования.НЕ: Это не решение!
Мой первый подход был:
Но это просто сводит long к int, потенциально создавая новые
Long
экземпляры или извлекая их из пула Long.Недостатки
Long.valueOf
создает новыйLong
экземпляр, если номер не входит вLong
диапазон пула [-128, 127].intValue
Реализация ничего не делает больше , чем:Так что это может считаться даже хуже, чем просто приведение
long
кint
.источник
Я утверждаю, что очевидным способом увидеть, изменилось ли приведение значения, было бы приведение и проверка результата. Я бы, однако, убрал лишний бросок при сравнении. Я также не слишком увлечен однобуквенными именами переменных (исключение
x
иy
, но не когда они означают строку и столбец (иногда соответственно)).Однако, действительно, я бы хотел избежать этого преобразования, если это вообще возможно. Очевидно, что иногда это невозможно, но в этих случаях
IllegalArgumentException
почти наверняка это неправильное исключение, которое нужно выбросить в отношении клиентского кода.источник
Целочисленные типы Java представлены как подписанные. С входом от 2 31 до 2 32 (или от -2 31 до -2 32 ) приведение будет успешным, но ваш тест не пройден.
На что нужно обратить внимание - все ли старшие биты
long
одинаковы:источник
(int) 0xFFFFFFFF
и(long) 0xFFFFFFFFL
имеют разные значения, но они оба содержат одну и ту же «информацию», и почти тривиально извлечь исходное длинное значение из int.но долго не может превышать максимум :)
источник
+ 0
ничего не добавляет к этому преобразованию, оно может работать, если Java обрабатывает конкатенацию числовых типов аналогично строкам, но поскольку вы не выполняете операцию добавления без причины.Еще одно решение может быть:
Я пробовал это для случаев, когда клиент делает POST и серверная БД понимает только целые числа, в то время как у клиента есть Long.
источник
Integer.valueOf(Long.MAX_VALUE.toString());
результате это вjava.lang.NumberFormatException: For input string: "9223372036854775807"
значительной степени запутывает исключение Out-Of-Range-Exception, поскольку теперь оно обрабатывается так же, как обрабатывается строка, содержащая буквы.