Pretvorba gubitaka u Javi

1. Pregled

U ovom brzom vodiču razgovarat ćemo o konceptu pretvorbe s gubicima u Javi i o razlozima iza toga.

Istodobno ćemo istražiti neke praktične tehnike pretvorbe kako bismo izbjegli ovu pogrešku.

2. Pretvorba gubitaka

Pretvorba gubitaka jednostavno je gubitak informacija tijekom rukovanja podacima.

U Javi to odgovara mogućnosti gubljenje vrijednosti ili preciznosti varijable tijekom pretvorbe jedan tip drugom.

Kada pokušamo dodijeliti varijablu od veliki tip do manjeg tipa, Java će generirati pogrešku, nekompatibilne vrste: moguća konverzija s gubitkom, tijekom sastavljanja koda.

Na primjer, pokušajmo dodijeliti dugo do an int:

long longNum = 10; int intNum = longNum;

Java će tijekom sastavljanja ovog koda izdati pogrešku:

nespojive vrste: moguća konverzija s gubitkom iz dugog u unutarnji

Ovdje će Java pronaći dugo i int nespojivo i rezultira pogreškom pretvorbe s gubitkom. Jer može biti dugo vrijednosti izvan int raspon -2,147,483,648 do 2,147,483,647.

Slično tome, pokušajmo dodijeliti plutati do a dugo:

float floatNum = 10,12f; long longNum = floatNum;
nekompatibilne vrste: moguća konverzija s gubitkom iz plutajućeg u dugi

Kao plutati mogu imati decimalne vrijednosti koje nemaju odgovarajuće dugo vrijednost. Stoga ćemo primiti istu pogrešku.

Slično tome, dodjeljivanje a dvostruko broj na an int će uzrokovati istu pogrešku:

dvostruki doubleNum = 1,2; int intNum = doubleNum;
nespojive vrste: moguća konverzija s gubicima iz dvostruke u int

The dvostruko vrijednosti mogu biti prevelike ili premale za int a decimalne vrijednosti će se izgubiti u pretvorbi. Dakle, to je potencijalna konverzija s gubitkom.

Također, možemo naići na ovu pogrešku tijekom izvođenja jednostavnog izračuna:

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

Kad dvostruko pomnoži s int, rezultat dobivamo u a dvostruko. Posljedično, to je također potencijalna konverzija s gubitkom.

Stoga nespojivi tipovi u pretvorba s gubicima može imati različite veličine ili vrste (cijeli brojevi ili decimale).

3. Primitivni tipovi podataka

U Javi postoje mnogi primitivni tipovi podataka s pripadajućim klasama omotača.

Dalje, sastavimo zgodan popis svih mogućih pretvorbi s gubicima u Javi:

  • kratak do bajt ili ugljen
  • ugljen do bajt ili kratak
  • int do bajt, kratak ili ugljen
  • dugo do bajt, kratak, ugljen ili int
  • plutati do bajt, kratak, ugljen, int ili dugo
  • dvostruko do bajt, kratak, ugljen, int, dugo ili plutati

Imajte na umu da ipak kratak i ugljen imaju istu veličinu. Još, pretvorba iz kratak do ugljen je gubitak jer ugljen je nepotpisana vrsta podataka.

4. Tehnike pretvorbe

4.1. Pretvaranje između primitivnih tipova

Jednostavan način pretvaranja primitiva kako bi se izbjegla pretvorba s gubitkom je spuštanje prema dolje; drugim riječima, lijevanje tipa veće veličine na tip manje veličine. Stoga se to naziva i sužavanjem primitivne konverzije.

Na primjer, pretvorimo dugo broj do a kratak koristeći downcasting:

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

Slično tome, pretvorimo a dvostruko do an int:

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

Međutim, trebali bismo imati na umu da pretvaranje velikoga tipa s vrijednostima koje su prevelike ili premale u manje veličine putem downcastinga može rezultirati neočekivanim vrijednostima.

Pretvorimo se dugo vrijednosti izvan raspona kratak:

long largeLongNum = 32768; kratki minShortNum = (kratki) largeLongNum; assertEquals (-32768, minShortNum); long smallLongNum = -32769; kratki maxShortNum = (kratki) smallLongNum; assertEquals (32767, maxShortNum);

Ako pažljivo analiziramo pretvorbu, vidjet ćemo da to nisu očekivane vrijednosti.

Drugim riječima, kada Java dosegne najveću vrijednost malog tipa dok pretvara iz velikog tipa, sljedeći je broj najniža vrijednost tipa male veličine i obrnuto.

Shvatimo to kroz primjere. Kada largeLongNum s vrijednošću od 32768 pretvara se u kratak, vrijednost shortNum1 je -32768. Budući da je maksimalna vrijednost kratak je 32767, dakle, Java ide za sljedeću minimalnu vrijednost kratak.

Slično tome, kada smallLongNum pretvara se u kratak. Vrijednost shortNum2 je 32767 dok Java ide za sljedeću maksimalnu vrijednost kratak.

Također, pogledajmo što će se dogoditi kada pretvorimo maksimalnu i minimalnu vrijednost a dugo do an 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. Pretvaranje između omotačkih predmeta i primitivnih tipova

Da bismo izravno pretvorili objekt omotača u primitiv, možemo koristiti razne metode u klasama omotača poput intValue (), kratka vrijednost () i longValue (). Ovo se zove Raspakirati.

Na primjer, pretvorimo a Plutati prigovoriti a dugo:

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

Također, ako pogledamo provedbu longValue ili slične metode, naći ćemo upotrebu sužavanja primitivne pretvorbe:

public long longValue () {return (duga) vrijednost; }

Međutim, ponekad treba izbjegavati sužavanje primitivne pretvorbe radi spremanja vrijednih podataka:

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

Nakon pretvorbe, vrijednost longNum bit će 15. Međutim, doubleNum je 15,9999, što je vrlo blizu 16.

Umjesto toga, možemo koristiti Matematika.okruženje () za pretvorbu u najbliži cijeli broj:

Double doubleNum = 15,9999; long longNum = Math.round (doubleNum); assertEquals (16, longNum);

4.3. Pretvaranje između omotanih predmeta

Za to se poslužimo već raspravljenim tehnikama pretvorbe.

Prvo ćemo pretvoriti omotački objekt na primitivnu vrijednost, spustite ga i pretvorite u drugi objekt omota. Drugim riječima, izvodit ćemo tehnike otpakiranja, spuštanja i boksa.

Na primjer, pretvorimo a Dvostruko prigovoriti an Cijeli broj objekt:

Double doubleNum = 10,3; dvostruki dbl = doubleNum.doubleValue (); // raspakiranje int intgr = (int) dbl; // spuštanje cijelog broja IntNum = Integer.valueOf (intgr); assertEquals (Integer.valueOf (10), intNum); 

Na kraju, koristimo Cijeli broj.vrijednost() pretvoriti primitivni tip int do an Cijeli broj objekt. Ova vrsta pretvorbe se naziva boks.

5. Zaključak

U ovom smo članku istražili koncept pretvorbe s gubicima u Javi uz pomoć nekoliko primjera. Osim toga, sastavili smo i zgodan popis svih mogućih konverzija s gubicima.

Usput smo identificirali sužavanje primitivne pretvorbe kao jednostavnu tehniku ​​pretvorbe primitivnih brojeva i izbjegavanja pogreške pretvorbe s gubitkom.

Istodobno smo istražili i dodatne praktične tehnike za numeričke pretvorbe u Javi.

Implementacije koda za ovaj članak mogu se naći na GitHubu.