Lossy Conversion in Java

1. Overzicht

In deze korte tutorial bespreken we het concept van verliesvrije conversie in Java en de reden erachter.

Tegelijkertijd zullen we enkele handige conversietechnieken onderzoeken om deze fout te voorkomen.

2. Omzetting met verlies

Lossy-conversie is simpelweg het verlies van informatie tijdens het verwerken van gegevens.

In Java komt het overeen met de mogelijkheid van de waarde of precisie van een variabele verliezen tijdens het converteren het ene type naar het andere.

Wanneer we proberen een variabele toe te wijzen van groot formaat naar een kleiner formaat, Java genereert een fout, incompatibele typen: mogelijke conversie met verlies, tijdens het compileren van de code.

Laten we bijvoorbeeld proberen een lang aan een int:

lang longNum = 10; int intNum = longNum;

Java geeft een foutmelding tijdens het compileren van deze code:

incompatibele typen: mogelijke conversie met verlies van lang naar int

Hier vindt Java lang en int incompatibel en resulteren in een conversiefout met verlies. Omdat er kan zijn lang waarden buiten de int bereik -2.147.483.648 tot 2.147.483.647.

Laten we op dezelfde manier proberen een vlotter naar een lang:

float floatNum = 10.12f; long longNum = floatNum;
incompatibele typen: mogelijke conversie met verlies van float naar long

Net zo vlotter kunnen decimale waarden hebben die niet overeenkomen lang waarde. Daarom krijgen we dezelfde foutmelding.

Evenzo wijst u een dubbele nummer naar een int zal dezelfde fout veroorzaken:

dubbele doubleNum = 1.2; int intNum = doubleNum;
incompatibele typen: mogelijke conversie met verlies van dubbel naar int

De dubbele waarden kunnen te groot of te klein zijn voor een int en decimale waarden gaan verloren in de conversie. Daarom is het een potentiële verlieslatende conversie.

We kunnen deze fout ook tegenkomen tijdens het uitvoeren van een eenvoudige berekening:

int fahrenheit = 100; int celcius = (fahrenheit - 32) * 5,0 / 9,0;

Wanneer een dubbele vermenigvuldig met een int, krijgen we het resultaat in een dubbele. Bijgevolg is het ook een mogelijk verliesgevende conversie.

Daarom zijn de incompatibele typen in Lossy-conversie kan verschillende grootten of typen hebben (gehele getallen of decimalen).

3. Primitieve gegevenstypen

In Java zijn er veel primitieve gegevenstypen beschikbaar met hun bijbehorende wrapper-klassen.

Laten we vervolgens een handige lijst samenstellen van alle mogelijke verliesgevende conversies in Java:

  • kort naar byte of char
  • char naar byte of kort
  • int naar byte, kort of char
  • lang naar byte, kort, char of int
  • vlotter naar byte, kort, char, int of lang
  • dubbele naar byte, kort, char, int, lang of vlotter

Merk echter op dat kort en char dezelfde maat hebben. Nog steeds, de conversie van kort naar char is lossy omdat char is een niet-ondertekend gegevenstype.

4. Conversietechnieken

4.1. Omzetten tussen primitieve typen

De gemakkelijke manier om primitieven te converteren om conversie met verlies te vermijden, is door middel van downcasting; met andere woorden, het grotere formaat naar een kleiner formaat gieten. Daarom wordt het ook wel vernauwende primitieve conversie genoemd.

Laten we bijvoorbeeld converteren een lange nummer naar een kort met behulp van downcasting:

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

Laten we op dezelfde manier een dubbele aan een int:

dubbel doubleNum = 15,6; int integerNum = (int) doubleNum; assertEquals (15, integerNum);

Houd er echter rekening mee dat het converteren van grote letters met te grote of te kleine waarden naar kleinere letters via downcasting kan resulteren in onverwachte waarden.

Laten we converteren lang waarden buiten het bereik van kort:

lang largeLongNum = 32768; short minShortNum = (short) largeLongNum; assertEquals (-32768, minShortNum); lang smallLongNum = -32769; kort maxShortNum = (kort) smallLongNum; assertEquals (32767, maxShortNum);

Als we de conversie zorgvuldig analyseren, zullen we zien dat dit niet de verwachte waarden zijn.

Met andere woorden, wanneer Java de hoogste waarde van een klein type bereikt tijdens het converteren van een groot type, het volgende nummer is de laagste waarde van het kleine type en vice versa.

Laten we dit aan de hand van voorbeelden begrijpen. Wanneer largeLongNum met de waarde van 32768 wordt geconverteerd naar kort, de waarde van shortNum1 is -32768. Omdat de maximale waarde van kort is 32767, daarom gaat Java voor de volgende min-waarde van de kort.

Evenzo, wanneer smallLongNum wordt geconverteerd naar kort. De waarde van shortNum2 is 32767 aangezien Java voor de volgende maximale waarde van de kort.

Laten we ook eens kijken wat er gebeurt als we de max- en min-waarden van a converteren lang aan een 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. Omzetten tussen wrapper-objecten en primitieve typen

Om een ​​wrapper-object direct naar een primitief te converteren, kunnen we verschillende methoden in wrapper-klassen gebruiken, zoals intValue (), shortValue () en longValue (). Dit heet uitpakken.

Laten we bijvoorbeeld een Vlotter bezwaar maken tegen een lang:

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

Ook als we kijken naar de implementatie van longValue of vergelijkbare methoden, we zullen het gebruik van versmallende primitieve conversie vinden:

openbare long longValue () {return (long) waarde; }

Soms moet echter een vernauwende primitieve conversie worden vermeden om waardevolle informatie op te slaan:

Dubbel doubleNum = 15.9999; lang longNum = doubleNum.longValue (); assertEquals (15, longNum); 

Na conversie is de waarde van longNum wordt 15. De doubleNum is 15.9999, wat heel dicht bij 16 is.

In plaats daarvan kunnen we gebruiken Math.round () voor conversie naar het dichtstbijzijnde gehele getal:

Dubbel doubleNum = 15.9999; long longNum = Math.round (doubleNum); assertEquals (16, longNum);

4.3. Omzetten tussen wrapper-objecten

Laten we hiervoor de reeds besproken conversietechnieken gebruiken.

Eerst zullen we converteren wrapper-object naar een primitieve waarde, downcast het en converteer het naar een ander wrapper-object. Met andere woorden, we zullen technieken voor unboxing, downcasting en boksen uitvoeren.

Laten we bijvoorbeeld een Dubbele bezwaar maken tegen een Geheel getal voorwerp:

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

Ten slotte gebruiken we Geheel getal.waarde van() om het primitieve type te converteren int aan een Geheel getal voorwerp. Dit type conversie wordt genoemd boksen.

5. Conclusie

In dit artikel hebben we het concept van verliesgevende conversie in Java onderzocht met behulp van een aantal voorbeelden. Daarnaast hebben we ook een handige lijst samengesteld met alle mogelijke verliesgevende conversies.

Onderweg hebben we vernauwende primitieve conversie geïdentificeerd als een gemakkelijke techniek om primitieve getallen te converteren en de verliesgevende conversiefout te vermijden.

Tegelijkertijd hebben we ook aanvullende handige technieken voor numerieke conversies in Java onderzocht.

De code-implementaties voor dit artikel zijn te vinden op GitHub.