Безопасное внесение long в int в Java
Какой самый идиоматический способ в 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;
}
Ответы
Ответ 1
Новый метод был добавлен с 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)
Ответ 2
Я думаю, что сделаю это как просто:
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;
}
Я думаю, что это выражает намерение более четко, чем повторное кастинг... но это несколько субъективно.
Обратите внимание на потенциальный интерес - в С# это будет просто:
return checked ((int) l);
Ответ 3
С Google Guava Ints ваш метод можно изменить на:
public static int safeLongToInt(long l) {
return Ints.checkedCast(l);
}
Из связанных документов:
checkedCast
public static int checkedCast(long value)
Возвращает значение int, равное value
, если возможно.
Параметры: value
- любое значение в диапазоне типа int
Возврат:значение int
, равное value
Броски: IllegalArgumentException
- если value
больше, чем Integer.MAX_VALUE
или меньше Integer.MIN_VALUE
Кстати, вам не нужна оболочка safeLongToInt
, если вы не хотите оставить ее на месте для изменения функциональности без тщательного рефакторинга, конечно.
Ответ 4
С BigDecimal:
long aLong = ...;
int anInt = new BigDecimal(aLong).intValueExact(); // throws ArithmeticException
// if outside bounds
Ответ 5
вот решение, в случае, если вы не заботитесь о ценности в случае, если оно больше, чем необходимо;)
public static int safeLongToInt(long l) {
return (int) Math.max(Math.min(Integer.MAX_VALUE, l), Integer.MIN_VALUE);
}
Ответ 6
Я утверждаю, что очевидный способ увидеть, изменило ли значение значения значение, было бы бросить и проверить результат. Тем не менее я бы удалил ненужный при сравнении. Я также не слишком увлечен именами переменных одной буквы (исключение 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
почти наверняка является ошибочным исключением, которое бросает в отношении кода клиента.
Ответ 7
DONT: Это не решение!
Мой первый подход:
public int longToInt(long theLongOne) {
return Long.valueOf(theLongOne).intValue();
}
Но это просто просто отдает длинный int, потенциально создавая новые экземпляры Long
или извлекая их из Long pool.
Недостатки
-
Long.valueOf
создает новый экземпляр Long
, если число не находится в пределах диапазона пула Long
[-128, 127].
-
Реализация intValue
не делает ничего:
return (int)value;
Таким образом, это можно считать еще хуже, чем просто отбрасывание Long
до int
.
Ответ 8
Целочисленные типы Java представлены как подписанные. При вводе между 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("...");
}
}
Ответ 9
(int) (longType + 0)
но Long не может превышать максимум:)
Ответ 10
Еще одно решение может быть:
public int longToInt(Long longVariable)
{
try {
return Integer.valueOf(longVariable.toString());
} catch(IllegalArgumentException e) {
Log.e(e.printstackstrace());
}
}
Я пробовал это для случаев, когда клиент делает POST, а серверная БД понимает только целые числа, в то время как у клиента есть Long.