Gegevenstypeconversie in java. Omzetten van primitieve typen in Java Baeldung

Java is een sterk getypeerde programmeertaal, wat betekent dat elke expressie en elke variabele al een goed gedefinieerd type heeft op het moment van compilatie.
Soorten geesten
Er zijn zeven soorten afgietsels in Java:

  • Identiteit;

  • Verbreding primitief;

  • Versmalling primitief;

  • Verbreding referentie;

  • Versmalling referentie;

  • Converteren naar string (String);

  • Verboden transformaties (verboden);
Laten we ze afzonderlijk bekijken.
identieke transformatie
De eenvoudigste is de identiteitstransformatie. In Java is het converteren van een uitdrukking van elk type naar exact hetzelfde type altijd legaal en succesvol.
Dit is belangrijk om vanuit theoretisch oogpunt te kunnen stellen dat elk type in Java kan deelnemen aan de transformatie, althans in het identieke.
Conversie van primitieve typen (expansie en contractie)
Voor eenvoudige typen betekent expansie dat er een overgang wordt gemaakt van een minder ruim type naar een meer ruim type. Bijvoorbeeld van type byte (lengte 1 byte) naar type int (lengte 4 bytes). Dergelijke conversies zijn veilig in die zin dat het nieuwe type altijd gegarandeerd alle gegevens bevat die in het oude type waren opgeslagen, en er dus geen gegevensverlies optreedt. Daarom implementeert de compiler het zelf, onopgemerkt door de ontwikkelaar:

byte b = 3;
int a = b;

De volgende 19 transformaties breiden zich uit:

  • Byte naar kort, int, lang, zwevend, dubbel

  • Kort naar int, lang, zwevend, dubbel

  • Van char naar int, long, float, double

  • Int te lang, zwevend, dubbel

  • Lang om te drijven, dubbel

  • Zweven om te verdubbelen
Merk op dat u niet kunt converteren naar char van typen met een kleinere of gelijke lengte (byte, short) of, omgekeerd, naar short van char zonder gegevens te verliezen. Dit komt omdat char, in tegenstelling tot andere integer-typen, is ondertekend.
Houd er echter rekening mee dat de gegevens, zelfs wanneer ze zijn uitgevouwen, nog steeds beschadigd kunnen zijn. Dit is het casten van int-waarden naar het float-type en het casten van long-waarden naar het float- of double-type. Hoewel deze fractionele typen veel grotere getallen bevatten dan hun overeenkomstige gehele getallen, hebben ze minder significante cijfers.
Bijvoorbeeld:

lange a = 11111111111111L;
vlotter f = een;
a = (lang) f; // () dit is precies de typeconversiebewerking
Systeem.uit.println (a); // resultaat 111111110656

Let op - vernauwing - betekent dat de overgang wordt uitgevoerd van een ruimer type naar een minder ruim type. Bij een dergelijke conversie bestaat het risico gegevens te verliezen. Als een aantal van het type int bijvoorbeeld groter was dan 127, dan gaan bij het casten naar byte de waarden van bits ouder dan de achtste verloren. In Java moet deze conversie expliciet worden gedaan, d.w.z. de programmeur in de code moet expliciet aangeven dat hij van plan is een dergelijke transformatie uit te voeren en klaar is om gegevens te verliezen.
De volgende 23 conversies worden kleiner:

  • Byte naar char

  • Kort tot byte, char

  • Char naar byte, kort

  • Int naar byte, kort, char

  • Lang naar byte, kort, char, int

  • Zweven naar byte, short, char, int, long

  • Dubbel naar byte, short, char, int, long, float
Bij het verkleinen van een integer type tot een smaller integer type, worden alle hoge-orde bits die niet in het nieuwe type vallen gewoon weggegooid. Er worden geen afrondingen of andere handelingen uitgevoerd om een ​​juister resultaat te verkrijgen:

Systeem.uit.println ((byte) 383);
Systeem.uit.println ((byte) 384);
Systeem.uit.println ((byte) -384);

Het resultaat zal zijn:

127
-128
-128
Het is te zien dat het tekenbit geen effect had tijdens vernauwing, omdat het gewoon werd weggegooid - het resultaat van het converteren van wederzijdse getallen (384, -384) bleek hetzelfde te zijn. Hierdoor kan niet alleen de exacte absolute waarde verloren gaan, maar ook het teken van de waarde.
Dit geldt ook voor char:

char c = 4000;
System.out.println ((kort) c);

Resultaat:

-25536
Conversie van referentietypes (expansie en krimp)
Objecttypeconversie kan het best worden geïllustreerd met behulp van een overervingsboom. Laten we eens kijken naar een klein voorbeeld van overerving:

klas Ouder (
int x;
}

klasse KindY verlengt Ouder (
int y;
}

klasse ChildZ verlengt Parent (
int z;
}

Elke klasse declareert een veld met een unieke naam. We zullen dit veld beschouwen als een voorbeeld van een reeks unieke eigenschappen die inherent zijn aan een bepaald objecttype.
Objecten van de klasse Parent hebben slechts één veld x, wat betekent dat alleen verwijzingen van het type Parent naar dergelijke objecten kunnen verwijzen. Objecten van de klasse ChildY hebben een y-veld en een x-veld geërfd van de Parent-klasse. Daarom kan naar dergelijke objecten worden verwezen met verwijzingen van het type ChildY of Parent. Voorbeeld:

Ouder p = nieuw KindY ();

Merk op dat deze p-referentie alleen kan verwijzen naar het x-veld van het gemaakte object. Het y-veld is niet beschikbaar omdat de compiler, bij het controleren van de juistheid van de uitdrukking p.y, niet kan voorspellen dat de referentie p tijdens runtime naar een object van het type ChildY zal verwijzen. Het analyseert alleen het type van de variabele zelf, en het wordt gedeclareerd als Parent, maar deze klasse heeft geen y-veld, wat een compilatiefout zal veroorzaken.
Evenzo hebben objecten van de ChildZ-klasse een z-veld en een x-veld dat is geërfd van de Parent-klasse. Dit betekent dat naar dergelijke objecten kan worden verwezen door verwijzingen zoals ChildZ en Parent.
Verwijzingen van het type Parent kunnen dus verwijzen naar een object van elk van de drie beschouwde typen, terwijl verwijzingen van het type ChildY en ChildZ alleen kunnen verwijzen naar objecten van exact hetzelfde type. U kunt nu overgaan tot het converteren van referentietypes op basis van zo'n overervingsboom.
Uitbreiding betekent een overgang van een meer specifiek type naar een minder specifiek type, d.w.z. overgang van kinderen naar ouders. Net als bij primitieve typen, wordt deze overgang indien nodig door de JVM zelf gemaakt en is deze "onzichtbaar" voor de ontwikkelaar, dat wil zeggen dat er geen speciale conversies voor nodig zijn.

Ouder p1 = nieuw KindY ();
Bovenliggende p2 = nieuwe ChildZ ();

In beide regels krijgen variabelen van het type Parent een waarde van een ander type toegewezen, waardoor de conversie plaatsvindt. Aangezien dit een extensie is, wordt dit automatisch en altijd met succes gedaan.
Opgemerkt moet worden dat er bij een dergelijke transformatie niets met het object zelf gebeurt. Ook al is bijvoorbeeld het y-veld van de klasse ChildY nu niet meer beschikbaar, dit betekent niet dat het is verdwenen. Een dergelijke significante verandering in het object is niet mogelijk. Het is afgeleid van de ChildY-klasse en behoudt al zijn eigenschappen. Alleen het type koppeling waarmee het object wordt benaderd, is gewijzigd.
De omgekeerde overgang, dat wil zeggen, de verplaatsing langs de overervingsboom naar de afstammelingen, is een vernauwing. In dit geval is het bijvoorbeeld een vernauwing om van een Parent-referentie, die kan verwijzen naar objecten van drie klassen, naar een ChildY-referentie, die slechts naar één van de drie klassen kan verwijzen, te gaan. Een dergelijke overgang is misschien niet mogelijk. Als een referentie van het type Parent verwijst naar een object van het type Parent of ChildZ, dan is overgang naar ChildY niet mogelijk, aangezien het object in beide gevallen geen veld y heeft, dat in de klasse ChildY wordt gedeclareerd. Daarom moet de ontwikkelaar bij het verfijnen expliciet aangeven dat het nodig is om te proberen een dergelijke transformatie uit te voeren. De JVM zal tijdens runtime de juistheid van de overgang controleren. Indien mogelijk wordt de conversie uitgevoerd. Als dit niet het geval is, wordt er een fout gegenereerd (meestal een ClassCastException).

Ouder p = nieuw KindY ();
KindY cy = (ChildY) p; //Rechtsaf
Bovenliggende p2 = nieuwe ChildZ ();
KindY cy2 = (ChildY) p2; //fout

Om te controleren of de gewenste sprong mogelijk is, kunt u de operator instanceof gebruiken:

Ouder p = nieuw KindY ();
if (p instantie van ChildY) (
KindY cy = (ChildY) p;
}

Bovenliggende p2 = nieuwe ChildZ ();
if (p2 instantie van ChildY) (
KindY cy = (ChildY) p2;
}

Bovenliggende p3 = nieuwe bovenliggende ();
if (p3 instantie van ChildY) (
KindY cy = (ChildY) p3;
}

In dit voorbeeld zullen er geen fouten optreden. De eerste transformatie is mogelijk en zal worden gerealiseerd. In het tweede en derde geval zullen de voorwaarden van de if-statements niet werken en zal er dus geen foutieve overgang zijn.
Converteren naar string
Elk type kan naar een string worden gegoten, d.w.z. naar een instantie van de klasse String. Deze conversie is uitzonderlijk omdat het absoluut alle typen omvat.
De verschillende typen worden als volgt naar string geconverteerd:

  • Numerieke typen worden in tekstvorm geschreven zonder verlies van precisie. Eerst wordt op basis van de primitieve waarde een instantie van de overeenkomstige klasse "wrapper" gemaakt, en vervolgens wordt de methode toString () erop aangeroepen. Maar aangezien deze acties van buitenaf onzichtbaar zijn, optimaliseert de JVM ze en zet primitieve waarden direct om naar tekst.

  • Booleaanse waarden worden naar de string "true" of "false" gegoten, afhankelijk van de waarde.

  • Voor objectwaarden wordt de methode toString () aangeroepen. Als de methode null retourneert, is het resultaat de tekenreeks "null".

  • Voor een null-waarde wordt de tekenreeks "null" gegenereerd.
Verboden conversies
Niet alle sprongen tussen willekeurige typen zijn toegestaan. Verboden conversies zijn bijvoorbeeld: overgangen van elk referentietype naar primitief en vice versa (behalve voor conversie naar een string), boolean kan alleen naar dit type of naar een string worden gegoten. Bovendien is het onmogelijk om klassen op aangrenzende takken van de overervingsboom naar elkaar toe te brengen. In het voorbeeld dat ik zag om referentietypes te illustreren, is de overgang van ChildY naar ChildZ verboden.
Hiermee is de lijst van verboden transformaties niet uitgeput. Het is vrij breed en tegelijkertijd zijn alle opties vrij duidelijk, dus ze zullen niet in detail worden overwogen. Geïnteresseerden kunnen volledige informatie krijgen van de specificatie.
Natuurlijk zal een poging om een ​​illegale conversie uit te voeren resulteren in een fout.

Geesten toepassen
De use-cases voor typeconversies kunnen als volgt worden gegroepeerd:

  • Waarden toekennen aan variabelen (toewijzing). Niet alle overgangen zijn toegestaan ​​in deze conversie - de beperkingen zijn zo gekozen dat er geen uitzondering kan worden gegenereerd.

  • Methode oproep. Deze conversie wordt toegepast op de argumenten van de aangeroepen methode of constructor. Deze cast geeft nooit aanleiding tot fouten. Casting wordt ook uitgevoerd bij het retourneren van een methodewaarde.

  • Expliciete casting. In dit geval wordt expliciet aangegeven naar welk type je de originele waarde wilt casten.

  • De concatenatie-operator converteert zijn argumenten naar de tekenreeks.

  • Numerieke uitbreiding. Voor numerieke bewerkingen kan het nodig zijn het type argument (en) te wijzigen. Deze conversie heeft een speciale naam - uitgebreid, omdat de keuze van het doeltype niet alleen kan afhangen van de beginwaarde, maar ook van het tweede argument van de bewerking.
Zoektocht # 8
Voeg aan het project het gebruik van dwang toe voor de hiërarchie van je klassen.

We eindigden ons laatste artikel met het feit dat ik beloofde je te vertellen welke typen kunnen worden gegoten en hoe het allemaal wordt gedaan. Laten we beginnen.

Gips in rekenkundige uitdrukkingen gebeurt automatisch.

byte-> kort-> int-> lang-> zwevend-> dubbel

Als de operanden a en b worden gecombineerd met een binaire operator (we zullen dit hieronder bespreken), worden beide operanden, voordat ze worden uitgevoerd, als volgt geconverteerd naar gegevens van hetzelfde type:

  • Als een van de operatoren van het type double is, wordt de tweede ook geconverteerd naar double;
  • Als een van de operators float is, wordt de andere ook geconverteerd naar float;
  • Als een van de operatoren lang is, wordt de tweede ook omgezet in lang;
  • Als een van de operatoren van het type int is, wordt de tweede ook geconverteerd naar int;

Toegestane typeconversies

De ononderbroken lijnen tonen de transformatie die is uitgevoerd zonder verlies van informatie. Deze omzetting gebeurt impliciet. Conversies waarbij informatieverlies kan optreden, worden casting genoemd. Ze worden weergegeven met stippellijnen. Als er geen regels zijn voor het gegevenstype in de figuur, dan is een dergelijke conversie onmogelijk. Verlies van informatie transformaties moeten zeer zorgvuldig worden gedaan. Dus, hoe kun je een aanzienlijk deel van de gegevens verliezen en kan het programma correct werken.

Voor de vernauwing van de kasten moet het expliciet worden gemaakt. Bijvoorbeeld: byte b = (byte) 128; int toegewezen aan bytetype.

Ik stel voor om een ​​paar voorbeelden te maken.

Je begrijpt deze code misschien niet een beetje, omdat ik nog niet heb uitgelegd wat een compiler is, constanten, enz. Verderop in de tutorial zal ik je alles vertellen, al had ik het eerder moeten doen. En nu wil ik beschrijven welke regels de namen van variabelen zouden moeten hebben.

  • Namen van variabelen mogen niet beginnen met een cijfer, ze kunnen niet in namen worden gebruikt als symbolen van rekenkundige en logische operatoren, evenals het '#'-teken.
  • De tekens '$' of '_' zijn acceptabel, inclusief de eerste positie en naam.
  • Een primitieve type variabele gedeclareerd als lid van een klasse (algemene variabele) is standaard ingesteld op nul.
  • Als een variabele in een methode als een lokale variabele wordt gedeclareerd, moet deze voor gebruik worden geïnitialiseerd. Omdat lokale variabelen niet standaard worden geïnitialiseerd. Dit betekent dat u een lokale variabele niet kunt declareren en niet geïnitialiseerd kunt laten. Dat wil zeggen, als volgt: int i ;. Als je dit in een methode doet, zal de compiler je vragen om de standaardwaarde in te stellen, terwijl de compiler deze op 0 maakt als een lid van een (globale) klasse een dergelijke variabele maakt.
  • Het bereik en de levensduur van een variabele wordt beperkt door het blok () waarin deze wordt gedeclareerd. Als u een variabele binnen de methode hebt gemaakt (zoals we in de voorbeelden hebben gedaan), kunt u deze niet buiten de methode gebruiken, omdat de methode wordt begrensd door haakjes (). De globale variabele is zichtbaar in alle blokken.
  • Het is ook verboden om de Java-gereserveerde woorden te gebruiken. De volledige lijst met trefwoorden is te zien in de onderstaande afbeelding.

En aangezien ik in dit artikel de uitdrukking van de binaire operator heb aangeroerd, stel ik voor om operators in Java te overwegen. Bovendien is er niet zo veel theorie.

Java heeft verschillende soorten operatoren: eenvoudige toewijzing, rekenkundig, unair, peer- en relationeel, conditioneel, typevergelijking, bitsgewijze en bit-offset.

Er zijn veel slimme woorden, maar deze foto zal alles heel eenvoudig uitleggen:

In eerste instantie zullen we bitsgewijze vergelijkings-, toewijzings- en postfix-operatoren gebruiken. Andere operators komen niet zo vaak voor, dus we zullen alleen kijken naar degene die we zullen gebruiken.

    openbare klasse OperatorsInJava (

    int a = 5;

    intb = 6;

    int som = a + b;

    int verschil = a - b;

Het is vaak nodig om strings om te zetten naar waarden van andere typen, zoals int of boolean, en vice versa. Volgens de geaccepteerde conventie is de verantwoordelijkheid voor het converteren van de string: v de waarde van een ander type wordt toegewezen aan de overeenkomstige methode van dat type. Het converteren van een string naar een int-waarde wordt bijvoorbeeld uitgevoerd door een statische methode uit de Integer-wrapperklasse. De volgende tabel bevat alle typen die kunnen worden geconverteerd van waarden naar tekenreeksen en vice versa, en geeft een overzicht van de bijbehorende methoden.

TYPE Methode om te converteren - Methode om te converteren van string

aan de lijn

boolean String.valueOf (boolean) nieuw.Boolean (String). booleaanse waarde ()

byte String.valueOf (byte) Byte.parseByte (string, int)

short String.valueOf (kort) Short.parseShort (string, int)

int String.valueOf (int) Integer.parseInteger (string, int)

lange String.valueOf (lang) Long.parseLong (String, int)

float String.valueOf (float) Float.parseFloat (String)

double String.valueOf (dubbel) Double.parseDouble (String)

Om een ​​tekenreeks om te zetten in een Booleaanse waarde, maakt u een Booleaans object en vraagt ​​u vervolgens naar de waarde ervan. Alle andere wrapper-klassen bevatten corresponderende methoden ontleden. Methoden: ontleden integer-typen bestaan ​​in twee overbelaste vormen: de eerste vereist, naast een string, een extra argument van het type int, dat de basis van het getallenstelsel vertegenwoordigt - van 2 tot 32; de tweede neemt alleen een stringparameter en gaat standaard uit van het gebruik van decimale notatie. In alle gevallen, behalve Boolean, wordt het volgende aangenomen: als de tekenreeks een waarde vertegenwoordigt die niet correct kan worden geconverteerd naar een getal van het juiste type, wordt een NumberFormatException gegenereerd. De klasse Boolean volgt de conventie dat elke parameterreeks die niet waar is (hoofdlettergevoelig) een booleaans object zal maken met de waarde false.

Methoden die tekens converteren die in een van de taalondersteunde vormen staan ​​(zoals \ b, \ uxxxx etc.), in een waarde van het type char en vice versa bestaat niet. Om een ​​String-object te krijgen dat één teken bevat, roept u gewoon de methode String.valueOf aan, waarbij u de juiste char-waarde als parameter doorgeeft.

Er zijn ook geen manieren om tekenreeksrepresentaties te maken van getallen die zijn gespecificeerd in een van de formaten die door de taal worden ondersteund - met een voorloopnul (O), die een octaal getal aangeeft, en het voorvoegsel Ox (of OX), dat dient als een teken van een hexadecimaal getalsysteem. Integer-wrapperklassen daarentegen ondersteunen versies van de decodeermethode die strings kunnen converteren naar numerieke waarden van het juiste type en begrijpen dat de leidende O een octaal getal aanduidt en een van de Ox OR Ox-prefixen hexadecimaal is.

Elke toepassingsklasse kan ondersteuning bieden voor het converteren van zijn eigen objecten naar tekenreeksen en vice versa, als zijn declaratie de methode toString op de juiste manier overschrijft en een speciale constructor levert die een object van de klasse creëert op basis van de tekenreeks die als parameter is doorgegeven. U hebt ook een methode String.valueOf (Object obj) die ofwel een "null" tekenreeksobject retourneert (als obj null is) of het resultaat van de methode obj.toString. De klasse String bevat voldoende overbelaste versies van de methode valueOf om elke waarde van elk type naar een String-object te converteren door simpelweg valueOf aan te roepen en het juiste argument door te geven.

Soms zijn er situaties waarin u een waarde van een bepaald type heeft en deze aan een variabele van een ander type moet toewijzen. Voor sommige typen kan dit zonder typeconversie, in dergelijke gevallen spreken we van automatische typeconversie. In Java is automatische conversie alleen mogelijk als de nauwkeurigheid van de doelvariabele voldoende is om de oorspronkelijke waarde op te slaan. Een dergelijke conversie vindt bijvoorbeeld plaats wanneer een letterlijke constante of de waarde van een variabele van het type byte of short wordt ingevoerd in een variabele van het type int. Het heet verlenging (verbreding) of toename (Promotie), omdat een type met een lagere bitdiepte wordt uitgebreid (opgeschaald) naar een groter compatibel type. De grootte van type int is altijd voldoende om getallen op te slaan in het bereik dat is toegestaan ​​voor typebyte, daarom is in dergelijke situaties een expliciete cast-operator niet vereist. Het omgekeerde is in de meeste gevallen niet waar, dus u moet de cast-operator gebruiken om een ​​int-waarde naar een bytevariabele te casten. Deze procedure wordt soms vernauwing (vernauwing), omdat u de vertaler expliciet vertelt om de waarde om te zetten zodat deze in een variabele van het gewenste type past. Om een ​​waarde naar een specifiek type te casten, moet u dit type specificeren, tussen haakjes, ervoor. Het volgende codefragment demonstreert het casten van een bron (variabele van type int) naar het type bestemming (variabele van type byte). Als tijdens een dergelijke bewerking de integerwaarde buiten het bereik zou vallen dat is toegestaan ​​voor het bytetype, zou het worden verminderd door modulo te delen door het toegestane bereik voor byte (het resultaat van het delen van modulo door een getal is de rest van deling door dit nummer) ,

int a = 100;
byteb = (byte) een;

2.2.1. Automatische typeconversie in uitdrukkingen

Bij het evalueren van de waarde van een uitdrukking moet de nauwkeurigheid die nodig is voor het opslaan van tussenresultaten vaak hoger zijn dan de nauwkeurigheid die nodig is om het eindresultaat weer te geven,

byte a = 40;
byte b = 50;
byte met = 100;
int d = a * b / s;

Het resultaat van de tussenliggende expressie (a * b) valt mogelijk buiten het bereik van waarden die zijn toegestaan ​​voor het bytetype. Dit is de reden waarom Java elk deel van de expressie automatisch promoot tot int, zodat er genoeg ruimte is voor het tussenresultaat (a * b).

Automatische typeconversie kan soms onverwachte vertaalfoutberichten veroorzaken. De onderstaande code bijvoorbeeld, hoewel deze er redelijk correct uitziet, resulteert in een foutmelding tijdens de vertaalfase. Daarin proberen we de waarde 50 * 2, die perfect in het bytetype zou moeten passen, in een bytevariabele te schrijven. Maar door de automatische conversie van het resultaattype naar int, krijgen we een foutmelding van de vertaler - immers, wanneer int in byte wordt ingevoerd, kan er een verlies aan precisie optreden.

byte b = 50;
b = b * 2:
^ Incompatibel type voor =. Expliciete cast nodig om int naar byte te converteren.
(Incompatibel type voor =. Expliciete conversie vereist)int inbyte)

Gecorrigeerde tekst:
byteb = 50;
b = (bytes) (b * 2);

waardoor b de juiste waarde van 100 invoert.

Als een expressie variabelen van de typen byte, short en int gebruikt, wordt het type van de hele expressie automatisch gepromoveerd tot int om overloop te voorkomen. Als het type van ten minste één variabele in de uitdrukking lang is, wordt het type van de hele uitdrukking ook gepromoveerd tot lang. Onthoud dat alle letterlijke gehele getallen die niet eindigen op een L (of 1) int zijn.

Als de uitdrukking operanden van het type float bevat, wordt het type van de gehele uitdrukking automatisch gepromoveerd tot float. Als ten minste één van de operanden van het type double is, wordt het type van de gehele expressie gepromoveerd tot double. Standaard behandelt Java alle literalen met drijvende komma als dubbel. Het volgende programma laat zien hoe het type van elke waarde in de uitdrukking wordt gepromoveerd om overeen te komen met de tweede operand van elke binaire operator.

klasse promoten (
public static void main (String args) (
byte b = 42;
char met= "een";
korte broek = 1024;
int i = 50000;
vlotter f = 5.67f;
verdubbeld = .1234;
dubbel resultaat = (f * b) + (i / c) - (d * s);
Systeem, uit. println ((f * b) + "+" + (i / c) + "-" + (d * s));
Systeem, uit. println ("resultaat =" + resultaat); )
}

De subexpressie f * b is een float vermenigvuldigd met een byte, dus het wordt automatisch gepromoveerd tot float. De volgende subexpressie i / c (int gedeeld door char) wordt gepromoveerd tot int. Evenzo wordt het type van de subexpressie d * s (dubbel keer kort) gepromoveerd tot verdubbelen. In de volgende stap van de berekeningen behandelen we drie tussenresultaten van de typen float, int en double. Ten eerste, wanneer de eerste twee bij elkaar worden opgeteld, wordt het int-type gepromoveerd tot zwevend en het resultaat is een zwevend type. Wanneer er een dubbele waarde van wordt afgetrokken, wordt het resultaattype gepromoveerd tot verdubbelen. Het eindresultaat van de hele uitdrukking is een dubbel.

Nu we bekend zijn met alle eenvoudige typen, inclusief gehele getallen en reële getallen, symbolen en booleaanse variabelen, gaan we proberen alle informatie bij elkaar te brengen. Het volgende voorbeeld maakt variabelen van elk van de eenvoudige typen en geeft de waarden van die variabelen weer.

klasse SimpleTypes (
public static void main (String args) (
byte b = 0x55;
korte s = 0x55ff;
int i = 1000000;
lang l = 0xffffffffL;
char met= 'A';
vlotter f = .25f;
dubbele d = .00001234;
booleaanse bool = waar;
Systeem.uit.println ("byte b =" + b);
System.out.println ("korte s =" + s);
System.out.println ("int i =" + i);
Systeem.uit.println ("lange 1 =" + l);
System.out.println ("char met= ”+ S);
System.out.println ("float f =" + f);
System.out.println ("dubbele d =" + d);
System.out.println ("boolean bool =" + bool);)
}

Door dit programma uit te voeren, zou u het onderstaande resultaat moeten krijgen:

byte b = 85
korte broek = 22015
int i = 1000000
lang 1 = 4294967295
char met= een
vlotter f = 0.25
dubbele d = 1.234e-005
booleaanse bool = waar

Merk op dat gehele getallen worden afgedrukt in decimale notatie, hoewel we voor sommige ervan waarden hebben gespecificeerd in hexadecimale notatie.

Dit artikel:

  • geschreven door het team. We hopen dat het nuttig voor u zal zijn. Veel leesplezier!
  • dit is een van de artikelen uit onze

Typeconversie is een onderwerp dat voor beginners met Java-programmering misschien ontmoedigend lijkt. Maar laten we je verzekeren dat het eigenlijk heel simpel is. Het belangrijkste om te begrijpen: volgens welke wetten vindt de interactie tussen variabelen plaats en onthoud dit bij het schrijven van programma's. Dus laten we het uitzoeken.

Er zijn 2 soorten transformaties in Java - een afbeelding om u te helpen:

Bedenk dat het hele Java-universum bestaat uit:

  • primitieve typen (byte, short, int, long, char, float, double, boolean)
  • voorwerpen

In dit artikel, wij:

  • overweeg typeconversie voor primitieve variabeletypen
  • conversie van objecten (String, Scanner, etc.) wordt in dit artikel niet behandeld, omdat er een aparte "magie" optreedt bij objecten - dit is een onderwerp voor een apart artikel.
Automatische conversie

Laten we proberen uit te zoeken wat "automatische conversie" is.

Denk eraan, toen we naar de soorten variabelen keken (in het artikel), zeiden we dat: een variabele is een soort "container" , die de waarde kan opslaan voor later gebruik in het programma. We hebben het ook gehad over het feit dat elk type variabele zijn eigen reeks geldige waarden en de hoeveelheid ingenomen geheugen heeft. Hier is het bord waar het allemaal is geschilderd:

Dit is dus waar we eigenlijk naar op weg zijn. Aan het feit dat het helemaal niet alleen was dat u de reeksen toegestane waarden en de hoeveelheid bezet geheugen kreeg 🙂

Laten we bijvoorbeeld vergelijken:

1.byte en kort. byte heeft een kleiner bereik van geldige waarden dan short. Dat wil zeggen, byte is als een kleinere doos en kort is een grotere doos. En dat betekent we kunnen byte in het kort nesten.

2.byte en int. byte heeft een kleiner bereik van geldige waarden dan int. Dat wil zeggen, byte is als een kleinere doos en int is een grotere doos. En dat betekent we kunnen byte nesten in int.

3. int en lang. int heeft een kleiner bereik van geldige waarden dan long. Dat wil zeggen, int is als een kleinere doos, en lang is een grotere doos. En dat betekent we kunnen er lang in nestelen.

Dit is een voorbeeld van automatische conversie. Dit kan schematisch worden weergegeven in de vorm van een afbeelding zoals deze:

Laten we eens kijken hoe dit in de praktijk werkt.

Voorbeeld 1

Code nummer 1 - als u deze code op uw computer uitvoert,

class Test (public static void main (String args) (byte a = 15; byte b = a; System.out.println (b);))

klasse Toets (

byte a = 15;

byte b = een;

Code nummer 2 - als u deze code op uw computer uitvoert, het nummer 15 wordt weergegeven in de console

class Test (public static void main (String args) (byte a = 15; int b = a; System.out.println (b);))

klasse Toets (

public static void main (String args) (

byte a = 15;

int b = een;

Systeem. uit. println (b);

En-en-en? Je denkt dat zodra hetzelfde nummer op de console was afgedrukt, en code #1 verschilt alleen van code #2 in het type variabele b zit er dan geen verschil tussen? NS dat is niet het geval.

Code nummer 2 bevat automatischtype conversie , maar in code # 1 - nee:

Hoewel het nummer in principe hetzelfde is, maar nu in b O Een grotere container die meer schijfruimte in beslag neemt. Tegelijkertijd voert de JVM automatische conversies voor u uit. Dat weet ze int meer dan byte .

Gips

Het is een andere zaak als u iets van een grotere container naar een kleinere probeert over te brengen.

U weet misschien dat de grotere container bevat wat in de kleine past - maar de JVM weet hier niets van en probeert te voorkomen dat u fouten maakt.

Daarom moet je “ronduit” zeggen dat de situatie onder controle is:

class Test (public static void main (String args) (int a = 0; long b = 15; a = (int) b;))

klasse Toets (

public static void main (String args) (

int a = 0;

lang b = 15;

a = (int) b;

Hier hebben we toegevoegd (int) voorkant B... Als de variabele een was, bijvoorbeeld, als byte, tussen haakjes zou zijn (byte)... De algemene formule ziet er als volgt uit:

Ze zegt "maak van (meer) betekenis" B een variabele van het (doel)type dat ik nodig heb int ".

Als er iets mis is gegaan.

Tot nu toe hebben we situaties bekeken, ervan uitgaande dat we precies weten wat we doen. Maar wat als je iets in een container probeert te doen dat daar niet past?

Het blijkt dat alleen wat "past" in de container blijft. Bijvoorbeeld, getallen met drijvende komma hebben het breukdeel "afgekapt":

// voorbeeld 1 class Test (public static void main (String args) (double a = 11.2345; int b = (int) a; System.out.println (b); // de console krijgt het nummer 11))

// voorbeeld 1

klasse Toets (

public static void main (String args) (

dubbele a = 11.2345;

int b = (int) een;

Systeem. uit. println (b); // de console geeft het nummer 11 . weer

Er moet aan worden herinnerd dat het fractionele deel niet afgerond, een weggegooid.

Wat gebeurt er als we een getal proberen te plaatsen dat buiten het bereik ligt? Als u bijvoorbeeld het getal 128 in byte invoert (bytebereik van -128 tot 127)? Denk je dat we er 1 krijgen? Nee. We krijgen -128:

class Test (public static void main (String args) (double a = 128; byte b = (byte) a; System.out.println (b); // in de console zullen we -128) zien)

De waarde van een variabele kan worden berekend met een dergelijke conversie, maar het doel van de programmeur is om een ​​situatie te voorkomen waarin de waarde buiten het bereik valt, omdat dit kan leiden tot een onjuiste werking van het programma.

Taken:
  1. Schrijf achtereenvolgens in de compiler de conversies van alle primitieve typen naar elkaar, inclusief char-typen, en maak een tabel van het volgende type:
byte kort char int lang vlot dubbele booleaans
byte
kort
char
int
Lang
Vlot
dubbele
booleaans

Schrijf op het snijpunt: a - als de transformatie automatisch plaatsvindt, op - als je een expliciete transformatie moet gebruiken, x - als de transformatie onmogelijk is.

* typecasting naar zichzelf heet identiek- het is niet nodig om het te registreren

  1. Kijk nog eens hoe groot elk primitief type is. Probeer een blokschema te maken dat laat zien waar welke typen passen. Teken de pijlen die verbredende transformatie en versmallende transformatie zeggen.
Vragen

Tijdens een sollicitatiegesprek voor de functie Junior Java Developer kan het zijn dat je gevraagd wordt:

Wat weet u over het converteren van primitieve gegevenstypen, is er gegevensverlies, is het mogelijk om een ​​booleaans type te converteren?

Probeer de vraag te beantwoorden.

Laten we samenvatten:
  • Als u de inhoud van een kleinere container in een grotere container "zet", gaat de conversie automatisch en mogen er geen fouten optreden.
  • Als het nodig is om "een waarde van een grotere container in een kleinere te plaatsen", moet u voorzichtig zijn en expliciet casten.
  • Bij het casten van float of double naar integer-types, wordt het fractionele deel niet afgerond, maar gewoon weggegooid.
  • Het booleaanse type wordt niet naar een van de typen gecast.
  • Het char-type wordt omgezet in numerieke typen, net als de UNICODE-tekencode.
  • Als het getal groter is dan de container, is het resultaat onvoorspelbaar.

Dit artikel beschrijft slechts een deel van het materiaal over het onderwerp typecasting. Er zijn ook objectcasts, casten naar een string (alles kan tenslotte in een string worden geschreven, toch?) en automatische typepromotie in expressies.

We hopen dat ons artikel nuttig voor u was. Het is ook mogelijk om je aan te melden voor onze Java cursussen in Kiev. We geven les vanaf nul. Uitgebreide informatie vindt u op onze website.