Conversão com perdas em Java

Conversão com perdas em Java

1. Visão geral

Neste tutorial rápido, discutiremos o conceito de conversão com perdas em Java e a razão por trás disso.

Ao mesmo tempo, exploraremos algumas técnicas de conversão úteis para evitar esse erro.

2. Conversão com perdas

A conversão com perdas é simplesmente a perda de informações durante o manuseio de dados. **

Em Java, corresponde à possibilidade delosing the value or precision of a variable while converting um tipo para outro.

Quando tentamos atribuir uma variável delarge-sized type to a smaller sized type, Java irá gerar um erro,incompatible types: possible lossy conversion, ao compilar o código.

Por exemplo, vamos tentar atribuir umlong a umint:

long longNum = 10;
int intNum = longNum;

Java emitirá um erro ao compilar este código:

incompatible types: possible lossy conversion from long to int

Aqui, o Java encontrarálongeint incompatíveis e resultará em erro de conversão com perdas. Porque pode haver valores delong fora do intervalo deint -2.147.483.648 a 2.147.483.647.

Da mesma forma, vamos tentar atribuir umfloat a umlong:

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

Comofloat pode ter valores decimais que não têm o valorlong correspondente. Portanto, receberemos o mesmo erro.

Da mesma forma, atribuir um númerodouble a umint causará o mesmo erro:

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

Os valores dedouble podem ser muito grandes ou muito pequenos para umint e os valores decimais serão perdidos na conversão. Portanto, é uma conversão potencial com perdas.

Além disso, podemos encontrar esse erro ao executar um cálculo simples:

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

Quando adouble se multiplica porint, obtemos o resultado em adouble. Consequentemente, é também uma conversão potencial com perdas.

Portanto, os tipos incompatíveis emlossy conversion can either have different sizes or types (inteiros ou decimais). **

3. Tipos de dados primitivos

Em Java, existem muitosprimitive data types disponíveis com seuswrapper classes correspondentes.

A seguir, vamos compilar uma lista útil de todas as conversões com perdas possíveis em Java:

  • short abyte ouchar

  • char abyte oushort

  • int abyte,short ouchar

  • long abyte,short,char ouint

  • float abyte,short,char,int oulong

  • double abyte,short,char,int,long oufloat

Observe que, emborashort echar tenham o mesmo tamanho. Ainda assim,the conversion from short to char is lossy because char is an unsigned data type.

4. Técnicas de conversão

4.1. Convertendo entre tipos primitivos

A maneira fácil deconverting primitives evitar a conversão com perdas é através do downcasting; em outras palavras, convertendo o tipo de tamanho maior em um tipo de tamanho menor. Por isso, também é chamado de estreitamento da conversão primitiva.

Por exemplo, vamos converter o númeroa long emshort usando redução de:

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

Da mesma forma, vamos converter umdouble em umint:

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

No entanto, devemos observar que a conversão de um tamanho grande com valores muito grandes ou muito pequenos para um tamanho menor por meio de downcasting pode resultar em valores inesperados.

Vamos converter os valores delong fora do intervalo deshort:

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

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

Se analisarmos cuidadosamente a conversão, veremos que esses não são os valores esperados.

Em outras palavras, quando o Java atinge o valor mais alto de um tipo de pequeno porte durante a conversão do tipo de grande porte,the next number is the lowest value do tipo de pequeno porte e vice-versa.

Vamos entender isso por meio de exemplos. QuandolargeLongNum com o valor de 32768 é convertido emshort, o valor deshortNum1 é -32768. Porque o valor máximo deshort é 32767, portanto , Java vai para o próximo valor mínimo deshort.

Da mesma forma, quandosmallLongNum é convertido emshort. O valor deshortNum2 é 32767 já que Java vai para o próximo valor máximo deshort.

Além disso, vamos ver o que acontece quando convertemos os valores máximos e mínimos delong emint:

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. Convertendo entre objetos wrapper e tipos primitivos

Para converter diretamente um objeto wrapper em um primitivo, podemos usar vários métodos em classes de wrapper, comointValue(),shortValue()elongValue(). Isso é chamado deunboxing.

Por exemplo, vamos converter um objetoFloat em umlong:

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

Além disso, se olharmos para a implementação delongValue ou métodos semelhantes, encontraremos o uso de redução da conversão primitiva:

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

No entanto, às vezes, o estreitamento da conversão primitiva deve ser evitado para salvar informações valiosas:

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

Após a conversão, o valor delongNum será 15. No entanto, odoubleNum é 15.9999, que está muito próximo de 16.

Em vez disso, podemos usarMath.round() para conversão para o inteiro mais próximo:

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

assertEquals(16, longNum);

4.3. Convertendo entre objetos Wrapper

Para isso, vamos usar as técnicas de conversão já discutidas.

Primeiro, vamos converterwrapper object to a primitive value, downcast it and convert it to another wrapper object. Em outras palavras, vamos executar técnicas de unboxing, downcasting e boxing.

Por exemplo, vamos converter um objetoDouble em um objetoInteger:

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

Por último, estamos usandoInteger.valueOf() para converter o tipo primitivoint em um objetoInteger. Este tipo de conversão é denominadoboxing.

5. Conclusão

Neste artigo, exploramos o conceito de conversão com perdas em Java com a ajuda de vários exemplos. Além disso, também compilamos uma lista útil de todas as conversões com perdas possíveis.

Ao longo do caminho, identificamos o estreitamento da conversão primitiva como uma técnica fácil para converter números primitivos e evitar o erro de conversão com perdas.

Ao mesmo tempo, também exploramos técnicas úteis adicionais para conversões numéricas em Java.

As implementações de código para este artigo podem ser encontradasover on GitHub.