Java converteert typen string naar int. Java-tekenreeksen converteren naar andere typen

Dit is een vrij groot onderwerp, maar we zullen proberen het zo volledig mogelijk en tegelijkertijd compact te beschouwen. We hebben dit onderwerp al gedeeltelijk aangeroerd toen we naar de primitieve typen Java keken.

Conversies tussen integer en floating point waarden zijn mogelijk in Java. Bovendien kunt u integer- en floating point-waarden converteren naar char-waarden en vice versa, aangezien elk teken overeenkomt met een Unicode-cijfer. In feite is het booleaanse type het enige primitieve type in Java dat niet kan worden geconverteerd naar een ander primitief type. Ook kan elk ander primitief type niet worden geconverteerd naar boolean.

Er zijn twee soorten conversies in Java: impliciet en expliciet.

Impliciete typeconversie wordt uitgevoerd als aan de volgende voorwaarden is voldaan:

  1. Beide typen zijn compatibel
  2. De lengte van het doeltype is groter dan of gelijk aan de lengte van het brontype

In alle andere gevallen moet worden gebruikt expliciete typeconversie.

Er zijn ook twee soorten transformaties:

  1. Verbreding conversie
  2. Conversie verkleinen

Verbredende transformatie ( verbreding conversie) treedt op wanneer een waarde van hetzelfde type wordt geconverteerd naar een breder type met een groter bereik aan geldige waarden. Java voert automatisch verbredende conversies uit, bijvoorbeeld als u een letterlijke int toewijst aan een dubbele of een ongewijzigde char aan een int. Impliciete conversie is altijd een verbredend type.

Maar hier kan het zijn eigen kleine harken hebben. Als u bijvoorbeeld een int-waarde converteert naar een float-waarde. En de int-waarde in binaire representatie heeft meer dan 23 significante bits, dan is het verlies van precisie mogelijk, aangezien het float-type 23 bits heeft toegewezen voor het gehele deel. Alle LSB's int-waarden die niet in de 23 bits van de float-mantisse passen, worden weggegooid, dus hoewel de volgorde van de getallen behouden blijft, gaat de precisie verloren. Hetzelfde geldt voor het converteren van lang naar dubbel.

Het verbreden van de conversie van het Java-type kan ook als volgt worden weergegeven:

Ononderbroken lijnen vertegenwoordigen conversies zonder verlies van gegevens. Stippellijnen duiden op verlies van precisie tijdens de conversie.

Het is de moeite waard om een ​​beetje uit te leggen waarom bijvoorbeeld het bytetype niet automatisch (niet expliciet) wordt geconverteerd naar het char-type, hoewel het bytetype 8 bits breed is en de char 16 bits breed, hetzelfde geldt voor de conversie van kort tot char. Dit komt omdat byte en short ondertekende gegevenstypen zijn, terwijl char niet-ondertekend is. Daarom moet u in dit geval expliciete casting gebruiken, omdat de compiler expliciet moet aangeven dat u weet wat u wilt en hoe het tekenbit van byte en korte typen zal worden verwerkt bij het converteren naar het char-type.

In de meeste gevallen is het gedrag van een char-waarde hetzelfde als dat van een integer-waarde; daarom kan een char-waarde overal worden gebruikt waar int- of long-waarden vereist zijn. Bedenk echter dat char niet-ondertekend is, dus het gedraagt ​​​​zich anders dan kort, ook al is het bereik van beide typen 16 bits.

kort s = ( kort ) 0xffff; // Deze bits vertegenwoordigen het getal -1
char C = "\ pfff"; // Dezelfde bits vertegenwoordigen het unicode-teken
int i1 = s; // Het converteren van short naar int geeft -1
int i2 = C; // Het converteren van char naar int geeft 65535

Versmallende transformatie ( versmallende conversie) treedt op wanneer een waarde wordt geconverteerd naar een waarde van een type waarvan het bereik niet groter is dan het origineel. Conversies verkleinen is niet altijd veilig: bijvoorbeeld het converteren van een geheel getal 13 naar een byte is logisch, maar het converteren van 13000 naar een byte is onverstandig, omdat byte alleen getallen van −128 tot 127 kan opslaan. Omdat gegevens verloren kunnen gaan tijdens een vernauwing conversie, maakt de Java-compiler bezwaar tegen een dergelijke conversie, zelfs als de te converteren waarde binnen het nauwere bereik van het opgegeven type valt:

int l = 13 ;
byte B = l ; // De compiler lost deze expressie niet op

De enige uitzondering op deze regel is het toewijzen van een integer literaal (int-waarde) aan een bytevariabele, of kort als de letterlijke waarde overeenkomt met het bereik van de variabele.

Beperkende conversies zijn altijd expliciete conversies..

Expliciete conversie van primitieve typen

De operator van expliciete typeconversie of, meer precies, typeconversies zijn haakjes, waarbinnen het type wordt aangegeven waarnaar de conversie wordt uitgevoerd - (type)... Bijvoorbeeld:

int l = 13 ;
byte B = ( byte ) l ; // Gedwongen conversie van int naar byte
l = ( int ) 13.456 ; // Gedwongen conversie van een letterlijke van het type double naar int 13

Gieten van primitieve typen wordt het meest gebruikt drijvende-kommawaarden converteren naar gehele getallen... Waarin het fractionele deel van de drijvende-kommawaarde wordt gewoon weggegooid(dat wil zeggen, de drijvende-kommawaarde wordt naar nul afgerond in plaats van naar het dichtstbijzijnde gehele getal). Eigenlijk alleen het gehele deel van het echte type wordt genomen en het is al gecast naar het type integer doel.

Bij het brengen van een meer ruime hele type tot minder ruime bits van hoge orde worden eenvoudigweg weggegooid... In wezen komt dit overeen met de werking van modulo de waarde die moet worden gegoten door het bereik van het doeltype (bijvoorbeeld voor het bytetype is dit 256).

Te groot breukgetal bij cast naar geheel getal wordt MAX_VALUE of MIN_VALUE.

Te groot dubbele wanneer gereduceerd tot vlot wordt Float.POSITIVE_INFINITY of Float.NEGATIVE_INFINITY.

De onderstaande tabel is een raster waarin voor elk primitief type is aangegeven naar welke typen ze kunnen worden geconverteerd en de conversiemethode. Brief N in de tabel betekent de onmogelijkheid van conversie. Brief ja betekent een verbredende conversie die automatisch wordt gedaan. Brief MET betekent een versmallende conversie die een expliciete cast vereist. Eindelijk, J * betekent een automatische verbredingsconversie, waarbij de waarde enkele van de minst significante cijfers kan verliezen. Dit kan gebeuren bij het converteren van int of long naar float of double. Typen met drijvende komma hebben een groter bereik dan typen met gehele getallen, dus int of long kan worden weergegeven als float of double. Typen met drijvende komma zijn echter benaderende getallen en bevatten mogelijk niet altijd zoveel significante bits in de mantisse als typen met gehele getallen.

Automatische type-uitbreiding in uitdrukkingen

Het is ook de moeite waard om de automatische promotie (uitbreiding) van typen in uitdrukkingen te vermelden. We zijn dit al tegengekomen toen we gegevenstypes van integers en bewerkingen daarop beschouwden, maar het is toch de moeite waard om er hier aan te herinneren om het nog beter te maken en bovendien is het direct gerelateerd aan dit onderwerp. In het onderstaande voorbeeld is het teken @ + , , * , / enzovoort.

Dat wil zeggen, alle letterlijke gehele getallen in uitdrukkingen, evenals typen byte, kort en char uitbreiden naar int ... Als, zoals hierboven beschreven, geen andere, grotere gegevenstypen ( lang, vlot of dubbele). Daarom geeft het bovenstaande voorbeeld een compilatiefout als de variabele C is van het type byte, en de uitdrukking b + 1, als resultaat van automatische promotie, heeft het type int.

Impliciete dwang in co-toewijzingsexpressies

Hoewel in deze paragraaf wordt gesproken over impliciete conversie (casting) van typen, hebben we de uitleg hier gegeven, aangezien in dit geval het automatisch uitbreiden van typen in expressies, en vervolgens impliciet casten van typen, ook werkt. Hier is een corps de ballet. Het onderstaande voorbeeld zal, denk ik, alles verduidelijken. Zoals in de vorige uitleg, het teken @ betekent elke geldige operator, bijvoorbeeld + , , * , / enzovoort.

Dit is de moeite waard om uit te leggen met een eenvoudig voorbeeld:

byte b2 = 50 ;
b2 = b2 * 2 ; // zal niet compileren
b2 *= 2 ; // zal compileren, hoewel het equivalent is aan b2 = b2 * 2

De tweede regel die in het voorbeeld wordt getoond, wordt niet gecompileerd vanwege automatische type-expansie in expressies, aangezien de expressie b2 * 2 van het type int is, omdat er automatische type-expansie is (integer-literalen in de expressie zijn altijd int). De derde regel zal gemakkelijk te compileren zijn, omdat de impliciete typecasting in de gecombineerde toewijzingsexpressie daarin zal werken.

Boksen / unboxen - primitieve typen converteren naar wrapper-objecten

Boksen en unboxin zijn ook vrij grote onderwerpen, maar ze zijn vrij eenvoudig.

Eigenlijk boksen en unboxen zijn primitieve typen van en naar wrapper-objecten.

Voor objecten van wikkels van primitieve typen is alles wat hierboven is gezegd van toepassing.

De wrapper-klassen werden vermeld in de tabellen bij het ontleden van elk van de primitieve typen. Maar toen was het slechts een vermelding in de tabel.

Dus voor elk primitief type is er zijn oudere broer, en het is helemaal niet primitief, maar is een echte klasse, met velden en methoden. En voor elk zo'n paar is automatische conversie mogelijk.

Meestal, als het programma veel wiskundige berekeningen heeft, is het beter om primitieve typen te gebruiken, omdat het sneller en zuiniger is in termen van middelen, maar soms is het nodig om een ​​primitief type naar een object te converteren.

Laat me je een eenvoudig voorbeeld geven:

int i3 ;
byte b2 = 3 ;
Byte mijnB ;
mijnB= b2;
mijnB++;
b2= mijnB;
i3= mijnB;

Als het nog niet duidelijk is waarom dit nodig is, dan is dit niet eng, leg gewoon een knoop als aandenken.

Elke expressie in Java heeft een type, dat wordt bepaald door de structuur van de expressie en de typen van de samenstellende operanden (constanten, variabelen en methoden). Soms moeten we echter een expressie expliciet naar een ander type converteren. Bovendien voert de Java-runtime in sommige situaties zelf dergelijke conversies impliciet uit.

Type conversie T 1 om T 2 te typen maakt het mogelijk dat een uitdrukking van het type T 1 tijdens het compileren wordt behandeld als een uitdrukking van het type T 2. In sommige gevallen is dit een puur syntactische constructie die geen invloed heeft op de gegenereerde code; in andere gevallen vereist de typeconversie extra acties tijdens runtime om de waarde van de uitdrukking te wijzigen of aanvullende controles op de juistheid van de toegepaste conversie. Voorbeelden:

  • Type conversie int in type lang vereist een 32-bits geheel getal om tijdens runtime uit te breiden tot een 64-bits geheel getal. In dit geval is er geen verlies van informatie.
  • Type conversie vlot in type lang vereist een niet-triviale conversie van een 32-bits zwevende waarde naar een 64-bits geheel getal tijdens runtime. Afhankelijk van de oorspronkelijke waarde kan er al dan niet informatie verloren gaan.
  • Het converteren van Thread naar Object is eenvoudig: aangezien Thread een afstammeling is van Object, is elke verwijzing naar een object van het type Thread automatisch een verwijzing naar een Object.
  • Voor het converteren van object naar thread is runtime-validatie vereist. Als de te converteren verwijzing inderdaad een verwijzing is naar een object van het type Thread, wordt deze geretourneerd als een conversieresultaat, anders wordt er een uitzondering gegenereerd.

5.4.1.1. Verbreding van nummerconversies

Verbreding van nummerconversies- dit zijn conversies van een numeriek type naar een "groter" numeriek type, die als veilig worden beschouwd, aangezien ze niet leiden tot het verlies van de waarde van de waarde die wordt geconverteerd. Dergelijke conversies in Java zijn:

  • transformaties byte v kort, int, lang, vlot en dubbele;
  • transformaties kort v int, lang, vlot en dubbele;
  • transformaties char v int, lang, vlot en dubbele;
  • transformaties int v lang, vlot en dubbele;
  • transformaties lang v vlot en dubbele;
  • transformaties vlot v dubbele.

In feite kan het converteren van een geheel getal naar een zwevende waarde leiden tot een verlies aan precisie, dat wil zeggen een verlies van significante cijfers. Dus het volgende voorbeeld:

Class Test (public static void main (String args) (int bigNumber = 1234567890; float geschatte = bigNumber; System.out.println (ongeveer);))

geeft de tekenreeks 1234567936 weer. Dit komt doordat bij het converteren int v vlot de resulterende waarde is 1.2345679E9 vanwege het feit dat de mantisse van getallen zoals vlot biedt plaats aan slechts 8 decimale cijfers (hier moet conversie naar type worden gebruikt om correct te werken) dubbele). Het runtime-systeem genereert echter nooit fouten bij het uitvoeren van de vermelde transformaties.

5.4.1.2. Getalconversies beperken

Getalconversies beperken- Dit zijn conversies van een numeriek type naar een "kleiner" numeriek type, wat kan leiden tot zowel verlies van grootte als verlies van precisie. Dergelijke conversies in Java zijn:

  • transformaties byte v char;
  • transformaties kort v byte en char;
  • transformaties int v byte, kort en char;
  • transformaties lang v byte, kort, int en char;
  • transformaties vlot v byte, kort, int, lang en char;
  • transformaties dubbele v byte, kort, int, lang, vlot en char;

We zullen hier niet in detail ingaan op de regels waarmee deze transformaties plaatsvinden, omdat ze intuïtief te begrijpen zijn en formeel nogal omslachtig. Bij het gebruik ervan is het belangrijk om te onthouden dat Java, in tegenstelling tot andere talen, geen overflow- of underflow-fouten genereert, dus de controle over de juistheid van de transformaties ligt volledig bij de programmeur.

5.4.1.3. Uitbreidbare linktransformaties

Uitbreidbare linktransformaties Zijn conversies van afgeleide referentietypen naar de typen van hun voorouders, die tijdens runtime geen actie vereisen en nooit fouten genereren. Dergelijke conversies in Java zijn:

  • het converteren van een klasse of interface naar zijn voorouder (in het bijzonder naar het objecttype);
  • het converteren van een klasse naar een interface die het implementeert;
  • het converteren van elke array naar objecttype of cloneable type;
  • het omzetten van een array van type S naar een array van type T als S en T referentietypes zijn en de conversie van S naar T groter wordt;
  • het converteren van een null-type naar een referentietype.

5.4.1.4. Linkconversies beperken

Linkconversies beperken Zijn conversies van afgeleide referentietypes naar hun afstammelingentypes. Deze conversies vereisen een runtime-controle van hun legitimiteit en kunnen een ClassCastException veroorzaken. Dergelijke conversies in Java zijn:

  • het converteren van een klasse naar zijn afstammeling (in het bijzonder het converteren van het objecttype naar een andere klasse);
  • het converteren van een klasse naar een interface wanneer de klasse niet definitief is en de gegeven interface niet implementeert (in het bijzonder het converteren van het objecttype naar een interface);
  • het converteren van het objecttype naar een willekeurige array;
  • het converteren van een interface naar een klasse die niet definitief is;
  • het converteren van een interface naar een klasse die definitief is en deze interface implementeert;
  • het converteren van de interface J naar de interface K, wanneer J geen afstammeling is van K, en er geen methode is gedeclareerd in zowel J als K met dezelfde signatuur, maar met verschillende resultaattypes;
  • het converteren van een array van type S naar een array van type T als S en T referentietypen zijn en de conversie van S naar T kleiner wordt.

5.4.1.5. Conversies naar strings

Elke uitdrukking in Java, inclusief nul, kan worden geconverteerd naar String.

5.4.1.6. Ongeldige conversies

De volgende typeconversies zijn verboden in Java:

  • het converteren van een referentietype naar een willekeurig primitief type;
  • het converteren van een primitief type naar een ander referentietype dan String;
  • het converteren van het nultype naar een primitief type;
  • conversies om null of type te typen booleaans;
  • type conversies booleaans naar een ander type dan het String-type;
  • het converteren van de ene klasse naar de andere, als geen van hen een voorouder is van de andere (behalve voor het converteren naar het String-type);
  • het converteren van een klasse naar een interface als de klasse definitief is en de gegeven interface niet implementeert;
  • het converteren van een klasse naar een array als de klasse verschilt van Object;
  • het converteren van een interface naar een klasse die definitief is en de gegeven interface niet implementeert (behalve voor het converteren naar het String-type);
  • het converteren van de J-interface naar de K-interface, als er een methode is gedeclareerd in zowel J als K met dezelfde handtekening, maar met verschillende resultaattypen;
  • het converteren van een array naar een andere klasse dan Object en String;
  • het converteren van een array naar een andere interface dan Cloneable;
  • het converteren van een array van type S naar een array van type T als het converteren van S naar T verboden is

5.4.2. Transformatiecontexten

5.4.2.1. Conversie in opdracht

Conversie in opdracht treedt op wanneer de waarde van een uitdrukking wordt toegewezen aan een variabele. Dit converteert het type van de uitdrukking naar het type van de variabele. Bij het toewijzen zijn verbredende typeconversies (zowel numeriek als referentie) altijd mogelijk. Een versmallende conversie is alleen mogelijk als aan de volgende voorwaarden wordt voldaan:

  • variabele is van het type byte, kort of char;
  • de uitdrukkingswaarde is een constante van het type int die binnen het bereik van mogelijke waarden van de variabele valt.

Bijvoorbeeld de byte-operator x = 123; laten we zeggen, aangezien de constante 123 (van type int) ligt in het bereik van toelaatbare waarden van het type byte.

Als het type van de expressie niet kan worden geconverteerd naar het type van de variabele, genereert de compiler een fout. Anders zeggen we dat het type van de uitdrukking opdracht compatibel met een variabel type. Dus het volgende fragment

Korte s = 123; char c = s; // genereert een compilatiefout

zal een fout genereren omdat de typen char en kort zijn incompatibel in toewijzing volgens de bovenstaande definities (de eerste is geïmplementeerd in 16-bits niet-ondertekende woorden en de tweede - met een teken).

5.4.2.2. Argumenten converteren

Argumenten converteren treedt op wanneer de werkelijke waarden van de argumenten worden geconverteerd naar het type parameters van een methode of constructor wanneer deze wordt aangeroepen. In dit geval zijn verbredende conversies van typen (zowel numeriek als referentie) altijd mogelijk en zijn versmallende conversies niet toegestaan. De redenen voor dit laatste verbod kunnen worden verklaard aan de hand van het volgende voorbeeld:

Class Test (static int m (byte a, int b) (return a + b;) static int m (short a, short b) (return a - b;) public static void main (String args) (System.out. println ( m (1, 2)); // genereert een compilatiefout))

Hier bevat de klasse Test twee methoden met dezelfde naam, die alleen verschillen in het type parameters. Als het beperken van argumentconversies in Java was toegestaan, zou de runtime moeten uitzoeken tot welke van deze methoden de aanroep van m (1, 2) behoort. Om dergelijke dubbelzinnigheden te vermijden, hebben de ontwikkelaars van de taal het probleem radicaal opgelost: ze verboden dergelijke methodeaanroepen. In deze situatie, om bijvoorbeeld de eerste methode aan te roepen, moeten we expliciet het type van de eerste operand specificeren (de tweede heeft al het standaardtype int), namelijk m ((byte) 1, 2).

5.4.2.3. Converteren naar string

Converteren naar string komt slechts in één geval voor: wanneer de binaire + bewerking wordt toegepast op twee operanden, waarvan er één van het type String is. In deze situatie wordt de tweede operand ook geconverteerd naar het type String en het resultaat van de bewerking is de aaneenschakeling van de resulterende strings. Dit proces wordt in meer detail beschreven in hfst. 5.14.

5.4.2.4. Expliciete type conversie

Expliciete type conversie treedt op wanneer een typecast expliciet wordt toegepast op een operand. In deze situatie kunnen alle hierboven beschreven typen typeconversies worden toegepast, behalve conversie naar een string. Een poging om expliciet te converteren naar een type dat hierboven als verboden is gemarkeerd, resulteert in een compilatiefout. Bovendien kan tijdens runtime een ClassCastException worden gegenereerd als de opgegeven conversie ongeldig is.

5.4.3. Numerieke operand type conversies

Typeconversie tijdens het evalueren van numerieke uitdrukkingen heeft een aantal kenmerken. Ze komen neer op twee gevallen: het omzetten van operanden in unaire operaties en in binaire operaties.

Alvorens unaire operatie uit te voeren:

  • als de operand van het type is byte, kort of char, het wordt geconverteerd naar type int;
  • in andere gevallen verandert het type niet.

Voordat u een binaire bewerking uitvoert:

  • als een van de operanden van het type is dubbele, dan wordt de tweede ook geconverteerd naar type dubbele;
  • vlot, dan wordt de tweede ook geconverteerd naar type vlot;
  • anders, als een van de operanden van het type is lang, dan wordt de tweede ook geconverteerd naar type lang;
  • anders worden beide operanden geconverteerd naar type int.

De vorige spreker beschreef de top-down transformatie vrij volledig, maar de bottom-up vereist (naar mijn mening) aanvullende uitleg, aangezien de vraag erg populair en interessant is.

Hoe expliciet casten werkt

Uw voorbeeld toont een opwaartse conversie ( Upcasting):

Lijst coll = nieuw ArrayList ();

Het vertaalt zich als volgt in het Russisch: maak een kraai, zoals een vogel. Maak een dynamische array zoals een blad. In de meeste situaties is een opwaartse conversie helemaal niet nodig.
Casten werkt echter in interviews als je vragen krijgt over erfenis. De site quizful.net bevat bijvoorbeeld over het algemeen veel vragen over typecasting. Daarom zal ik de functies die ik ken uitleggen.

Dus in het bovenstaande voorbeeld hebben we een object van het type ArrayList gemaakt en een verwijzing van het type List. Onthoud de axioma's voor deze methode:

1. De link kan naar elke ouder verwijzen. Zelfs heel lang geleden. Dat wil zeggen, u kunt coll zelfs casten om Object te typen. De compiler slaat elke verwijzing naar de klasse van de ouder over, of ouder-ouder, of ouder-ouder ... ouder

2. Verwijzend naar het veld - het referentieveld wordt altijd geretourneerd, niet het objectveld. Als een dergelijk veld niet aanwezig is in de referentieklasse, treedt er een compilatiefout op.

Klasse A (int x = 2; // Veld van de bovenliggende klasse) Klasse B breidt A uit (int x = 3; // Veld dat de bovenliggende klasse moet overlappen int y = 5; // Veld dat zich niet in de bovenliggende klasse bevindt.) Class Test (public static void main (String args) (A ab = new B (); // Upward conversion System.out.println ("Int x =" + ab.x);))

Zal terugkeren Int x = 2 ... Als u toegang probeert te krijgen tot een objectveld:

System.out.println ("Int y =" + ab.y); // Compilatiefout

Uw compiler zal zeggen dat u het bij het verkeerde eind heeft, aangezien het een dergelijk veld niet als referentie ziet (A ab). Al het bovenstaande blijft geldig, zelfs als uw velden zijn gemarkeerd met statische modifiers.

3. Een niet-statische methode aanroepen: in dit geval wordt de methode van het object geretourneerd. Maar bij toegang tot een statische methode wordt de referentiemethode geretourneerd.

Klasse D (public void doSome () (// Nonstatic method System.out.println ("Nonstatic doSome from D"));) public static void Action () (// Static method System.out.println ("static Action from D") ");)) public class Okey breidt D uit (public void doSome () (System.out.println (" doSome from Okey ");) public static void Action () (System.out.println (" static Action from Okey " );) public static void main (String args) (D o = new Okey (); o.doSome (); // Van de Okey-klasse o.Action (); // Van de D-klasse))

Niet-statische doSome van Okey

statische actie van D

Het antwoord is simpel, een niet-statische methode is een objectmethode, een statische methode is een klassenmethode. Wanneer we een niet-statische methode aanroepen, begrijpt de compiler dit: vliegen als een kraai. Als we statisch noemen - letterlijk, vlieg als een vogel.

4. Als er een aanroep is van een methode die wordt beschreven in de objectklasse, maar niet wordt beschreven in de referentieklasse, treedt er een compilatiefout op. Omdat de methode door verwijzing wordt aangeroepen:

Klasse A () Klasse B breidt A uit (void someMethod () (); public static void main (String args) (A ab = new B (); ab.someMethod (); // Compilatiefout.))

5. De constructor van een object (wanneer gemaakt met het nieuwe commando) werkt hetzelfde alsof je een verwijzing naar je klasse geeft.

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.

annotatie: Deze lezing is gewijd aan de problematiek van typeconversie. Omdat Java een sterk getypeerde taal is, houden de compiler en de virtuele machine altijd het type bij om ervoor te zorgen dat het programma betrouwbaar werkt. In veel gevallen is echter een of andere transformatie nodig om de logica van het programma te implementeren. Aan de andere kant staat Java toe dat sommige veilige typeovergangen worden uitgevoerd op een impliciete manier voor de ontwikkelaar, wat kan leiden tot misverstanden over het programma. De lezing gaat in op alle soorten transformaties, en vervolgens op alle situaties in het programma waar ze kunnen worden toegepast. Het besluit door een classificatie te starten van de soorten variabelen en de soorten waarden die ze kunnen opslaan. Deze kwestie zal in de volgende colleges in meer detail worden besproken.

Wat betekent dit allemaal? Laten we op volgorde beginnen. 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;

Op de laatste regel wordt de bytewaarde van b automatisch geconverteerd naar a (dat wil zeggen int); hiervoor zijn geen speciale stappen vereist.

De volgende 19 transformaties breiden zich uit:

  • byte naar short, int, long, float, double
  • 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, niet is ondertekend.

Houd er echter rekening mee dat zelfs bij uitbreiding de gegevens in speciale gevallen nog steeds kunnen worden beschadigd. Ze zijn al behandeld in de vorige lezing, dit is het gieten van int-waarden naar het float-type en het gieten van lange waarden naar het float- of dubbele type. Hoewel deze fractionele typen veel grotere getallen kunnen bevatten dan hun overeenkomstige gehele getallen, hebben ze minder significante cijfers.

Laten we dit voorbeeld herhalen:

lange a = 11111111111111L; vlotter f = een; a = (lang) f; afdrukken (a);

Het resultaat zal zijn:

De inverse transformatie - 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, gaan de waarden van bits ouder dan de achtste verloren wanneer het naar byte wordt gecast. 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 conversie uit te voeren en klaar is om gegevens te verliezen.

De volgende 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, kort, char, int, lang
  • van 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 passen gewoon weggegooid. Er worden geen afrondingen of andere handelingen uitgevoerd om een ​​juister resultaat te verkrijgen:

afdrukken ((byte) 383); afdrukken ((byte) 384); afdrukken ((byte) -384);

Het resultaat zal zijn:

Het is te zien dat het tekenbit geen effect had tijdens vernauwing, omdat het gewoon werd weggegooid - het resultaat van het converteren van tegengestelde getallen (384 en -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 het char-type:

char c = 40000; print ((kort) c);

Het resultaat zal zijn:

Het reduceren van een fractioneel type tot een integer type is complexer. Het wordt in twee fasen uitgevoerd.

In de eerste stap wordt de fractionele waarde geconverteerd naar long als het doeltype long is, of anders naar int (het doeltype is byte, short, char of int). Om dit te doen, wordt het oorspronkelijke fractionele getal eerst wiskundig afgerond naar nul, dat wil zeggen dat het fractionele deel eenvoudigweg wordt weggegooid.

Bijvoorbeeld, 3,84 wordt afgerond op 3 en -3,84 wordt -3. In dit geval kunnen zich speciale gevallen voordoen:

  • als de oorspronkelijke fractionele waarde NaN is, dan is het resultaat van de eerste stap 0 van het geselecteerde type (d.w.z. int of long);
  • als de initiële fractionele waarde positief of negatief oneindig is, dan is het resultaat van de eerste stap respectievelijk de maximaal of minimaal mogelijke waarde voor het geselecteerde type (d.w.z. voor int of long);
  • tenslotte, als de fractionele waarde een eindige waarde was, maar als resultaat van afronding, een getal dat te groot is in absolute waarde voor het geselecteerde type (dwz voor int of long), dan, zoals in de vorige paragraaf, het resultaat van de eerste stap is respectievelijk de maximaal of de minimaal mogelijke waarde van dit type. Als het afrondingsresultaat in het waardenbereik van het geselecteerde type past, is dit het resultaat van de eerste stap.
  • en int zijn vrij duidelijk - fractionele oneindigheden zijn geconverteerd naar respectievelijk de minimaal en maximaal mogelijke waarden van deze typen. Het resultaat voor de volgende drie typen (short, char, byte) is in feite een verdere vernauwing van de waarden die zijn verkregen voor int, volgens de tweede stap van de conversieprocedure. En dit wordt gedaan, zoals beschreven, door simpelweg de meest significante bits weg te gooien. Laten we niet vergeten dat de kleinst mogelijke waarde in bitvorm wordt weergegeven als 100..000 (slechts 32 bits voor int, dat wil zeggen, één en 31 nullen). Het maximaal mogelijke is 1111..111 (31 eenheden). Door de meest significante bits weg te gooien, krijgen we het resultaat 0 voor negatief oneindig, wat hetzelfde is voor alle drie typen. Voor positieve oneindig krijgen we een resultaat waarvan alle bits gelijk zijn 1

    Vestig tot slot nogmaals de aandacht op het feit dat primitieve waarden van het booleaanse type alleen kunnen deelnemen aan identieke conversies.