Рубрики
Без рубрики

Преобразование с потерями в Java

Узнайте о преобразовании с потерями в Java и некоторых удобных методах преобразования, чтобы избежать этой ошибки

Автор оригинала: baeldung.

1. Обзор

В этом кратком руководстве мы обсудим концепцию преобразования с потерями в Java и причину этого.

В то же время мы рассмотрим некоторые удобные методы преобразования, чтобы избежать этой ошибки.

2. Преобразование С Потерями

Преобразование с потерями-это просто потеря информации при обработке данных.

В Java это соответствует возможности потери значения или точности переменной при преобразовании одного типа в другой.

Когда мы пытаемся назначить переменную типа большого размера типу меньшего размера , Java генерирует ошибку, несовместимые типы: возможное преобразование с потерями , при компиляции кода.

Например, давайте попробуем назначить long для int :

long longNum = 10;
int intNum = longNum;

Java выдаст ошибку при компиляции этого кода:

incompatible types: possible lossy conversion from long to int

Здесь Java найдет long и int несовместимыми и приведет к ошибке преобразования с потерями. Потому что могут быть длинные значения за пределами int диапазона от -2,147,483,648 до 2,147,483,647.

Аналогично, давайте попробуем назначить float a long :

float floatNum = 10.12f;
long longNum = floatNum;
incompatible types: possible lossy conversion from float to long

Поскольку float может иметь десятичные значения, которые не имеют соответствующего long значения. Поэтому мы получим ту же ошибку.

Аналогично, присвоение double номера int приведет к той же ошибке:

double doubleNum = 1.2;
int intNum = doubleNum;
incompatible types: possible lossy conversion from double to int

Значения double могут быть слишком большими или слишком маленькими для int , и десятичные значения будут потеряны при преобразовании. Следовательно, это потенциальное преобразование с потерями.

Кроме того, мы можем столкнуться с этой ошибкой при выполнении простого вычисления:

int fahrenheit = 100;
int celcius = (fahrenheit - 32) * 5.0 / 9.0;

Когда double умножается на int , мы получаем результат в double . Следовательно, это также потенциальное преобразование с потерями.

Поэтому несовместимые типы в преобразовании с потерями могут иметь разные размеры или типы (целые или десятичные числа).

3. Примитивные Типы данных

В Java существует множество примитивных типов данных, доступных с соответствующими классами-оболочками .

Далее давайте составим удобный список всех возможных преобразований с потерями в Java:

  • short to byte или char
  • char to байт или короткий
  • int to byte , short или char
  • long to byte , short , char или int
  • float to byte , short , char , int или long
  • double to byte , short , char , int , long или float

Обратите внимание, что хотя short и char имеют одинаковый размер. Тем не менее, преобразование из short в char приводит к потерям, поскольку char является типом данных без знака .

4. Методы преобразования

4.1. Преобразование Между Примитивными Типами

Простой способ преобразования примитивов, чтобы избежать преобразования с потерями,-это понижение; другими словами, приведение типа большего размера к типу меньшего размера. Следовательно, это также называется сужением примитивного преобразования.

Например, давайте преобразуем длинное число в короткое с помощью понижающей передачи :

long longNum = 24;
short shortNum = (short) longNum;
assertEquals(24, shortNum);

Аналогично, давайте преобразуем double в int :

double doubleNum = 15.6;
int integerNum = (int) doubleNum;
assertEquals(15, integerNum);

Однако следует отметить, что преобразование типа большого размера со слишком большими или слишком маленькими значениями в тип меньшего размера с помощью понижения может привести к неожиданным значениям.

Давайте преобразуем длинные значения за пределами диапазона короткие :

long largeLongNum = 32768; 
short minShortNum = (short) largeLongNum;
assertEquals(-32768, minShortNum);

long smallLongNum = -32769;
short maxShortNum = (short) smallLongNum;
assertEquals(32767, maxShortNum);

Если мы внимательно проанализируем конверсию, то увидим, что это не ожидаемые значения.

Другими словами, когда Java достигает наибольшего значения типа малого размера при преобразовании из типа большого размера, следующее число является наименьшим значением типа малого размера и наоборот.

Давайте разберемся в этом на примерах. Когда большое длинное число со значением 32768 преобразуется в короткое , значение короткое число 1 равно -32768 . Поскольку максимальное значение short равно 32767, поэтому Java переходит к следующему минимальному значению short.

Аналогично, когда маленькое длинное число преобразуется в короткое . Значение short Num2 равно 32767, поскольку Java переходит к следующему максимальному значению short .

Кроме того, давайте посмотрим, что произойдет, когда мы преобразуем максимальные и минимальные значения a long в int :

long maxLong = Long.MAX_VALUE; 
int minInt = (int) maxLong;
assertEquals(-1, minInt);

long minLong = Long.MIN_VALUE;
int maxInt = (int) minLong;
assertEquals(0, maxInt);

4.2. Преобразование между объектами-оболочками и примитивными типами

Чтобы напрямую преобразовать объект-оболочку в примитив, мы можем использовать различные методы в классах-оболочках, такие как int Value () , shortValue() и longValue() . Это называется распаковка .

Например, давайте преобразуем объект Float в объект long :

Float floatNum = 17.564f;
long longNum = floatNum.longValue();
assertEquals(17, longNum);

Кроме того, если мы посмотрим на реализацию long Value или аналогичных методов, мы найдем применение сужающего примитивного преобразования:

public long longValue() {
    return (long) value;
}

Однако иногда следует избегать сужения примитивного преобразования, чтобы сохранить ценную информацию:

Double doubleNum = 15.9999;
long longNum = doubleNum.longValue();
assertEquals(15, longNum);

После преобразования значение long Num будет равно 15. Однако двойное число равно 15.9999, что очень близко к 16.

Вместо этого мы можем использовать Math.round() для преобразования в ближайшее целое число:

Double doubleNum = 15.9999;
long longNum = Math.round(doubleNum);

assertEquals(16, longNum);

4.3. Преобразование Между Объектами-Оболочками

Для этого давайте воспользуемся уже рассмотренными методами преобразования.

Сначала мы преобразуем объект-оболочку в примитивное значение, опустим его и преобразуем в другой объект-оболочку . Другими словами, мы будем выполнять техники распаковки, даункастинга и бокса.

Например, давайте преобразуем объект Double в объект Integer :

Double doubleNum = 10.3;
double dbl = doubleNum.doubleValue(); // unboxing
int intgr = (int) dbl; // downcasting
Integer intNum = Integer.valueOf(intgr);
assertEquals(Integer.valueOf(10), intNum);

Наконец, мы используем Integer . valueOf() для преобразования примитивного типа int в Целое число объект. Этот тип преобразования называется boxing .

5. Заключение

В этой статье мы исследовали концепцию преобразования с потерями в Java с помощью ряда примеров. Кроме того, мы также составили удобный список всех возможных конверсий с потерями.

Попутно мы определили сужение примитивного преобразования как простой метод преобразования примитивных чисел и избежания ошибки преобразования с потерями.

В то же время мы также изучили дополнительные удобные методы числовых преобразований в Java.

Реализации кода для этой статьи можно найти на GitHub .