Cum se configurează smartphone-uri și PC-uri. Portal informativ
  • Acasă
  • OS
  • Lansarea unui șir într-un număr java. Conversia șirurilor de caractere Java în alte tipuri de valori

Lansarea unui șir într-un număr java. Conversia șirurilor de caractere Java în alte tipuri de valori

Acesta este un subiect destul de amplu, dar vom încerca să îl luăm în considerare cât mai complet și, în același timp, cât mai compact posibil. Am atins deja parțial acest subiect când ne-am uitat la tipurile Java primitive.

În Java, conversiile între valorile întregi și în virgulă mobilă sunt posibile. De asemenea, puteți converti valorile întregi și în virgulă mobilă în valori de caractere și invers, deoarece fiecare caracter corespunde unei cifre Unicode. De fapt, tipul boolean este singurul tip primitiv din Java care nu poate fi convertit într-un alt tip primitiv. În plus, orice alt tip primitiv nu poate fi convertit în boolean.

Există două tipuri de conversie de tip în Java: implicitȘi explicit.

Conversie implicită de tip se execută dacă sunt îndeplinite următoarele condiții:

  1. Ambele tipuri sunt compatibile
  2. Lungime tipul tinta mai mare sau egală cu lungimea tipului original

În toate celelalte cazuri, trebuie utilizat conversie explicită de tip.

Există, de asemenea, două tipuri de transformări:

  1. Lărgirea conversiei
  2. Îngustarea conversiei

Transformare în extindere ( lărgirea conversiei) apare atunci când o valoare de un tip este convertită într-un tip mai larg, cu un interval mai mare valori acceptabile. Java efectuează automat conversii de extindere, de exemplu, dacă atribuiți un literal int unei variabile duble sau valoarea unei variabile char unei variabile int. Conversia implicită are întotdeauna un tip de extensie.

Dar aceasta poate avea propriile sale mici greble. De exemplu, dacă o valoare int este convertită într-o valoare float. Și valoarea lui int în reprezentarea binară este mai mare decât 23 biți semnificativi, atunci este posibilă o pierdere de precizie, deoarece tipul float are 23 de biți alocați pentru partea întreagă. Toți biți mici valorile int care nu se încadrează în cei 23 de biți ai mantisei flotante vor fi aruncate, așa că, deși ordinea numărului va fi păstrată, precizia se va pierde. Același lucru este valabil și pentru conversie tip lung a tasta double.

Extinderea conversiei tipurilor Java poate fi, de asemenea, descrisă după cum urmează:

Linii continue denotă transformări efectuate fără pierderi de date. Liniile întrerupte indică faptul că poate apărea o pierdere de precizie în timpul conversiei.

Merită să explicăm puțin de ce, de exemplu, tipul octet nu este convertit automat (nu explicit) în tipul char, deși tipul octet are o lățime de 8 biți și char este 16, același lucru se aplică și conversiei de tipul scurt la char. Acest lucru se întâmplă deoarece byte și short sunt tipuri de date semnate, iar char este nesemnat. Prin urmare, în în acest caz, Trebuie să utilizați tipul de turnare explicit, deoarece trebuie să spuneți în mod explicit compilatorului că știți ce doriți și cum vor fi gestionați bitul semn al tipurilor de octet și scurt la conversia în char.

Comportamentul unei valori char este în cele mai multe cazuri același cu comportamentul unei valori de tip întreg, prin urmare, o valoare char poate fi utilizată oriunde este necesară o valoare int sau long. Totuși, amintiți-vă că tipul char este nesemnat, deci se comportă diferit față de tipul scurt, chiar dacă ambele tipuri au o gamă de 16 biți.

mic de statura s = ( mic de statura ) 0xffff; // Acești biți reprezintă numărul -1
char c = „\uffff”; // Aceiași biți reprezintă caracterul unicode
int i1 = s; // Convertirea scurtă în int dă –1
int i2 = c; // Convertirea char în int dă 65535

Transformare de îngustare ( îngustarea conversiei) apare atunci când o valoare este convertită într-o valoare de tip al cărui interval nu este mai mare decât cel original. Conversiile de restrângere nu sunt întotdeauna sigure: de exemplu, conversia valorii întregi 13 într-un octet are sens, dar conversia 13000 într-un octet este neînțeleaptă, deoarece octetul poate stoca doar numerele de la -128 la 127. Deoarece datele se pot pierde în timpul unei restrângeri conversie, compilatorul Java obiectează la orice astfel de conversie, chiar dacă valoarea convertită se încadrează într-un interval mai restrâns de tipul specificat:

int i = 13 ;
octet b = i ; // Compilatorul nu va permite această expresie

Singura excepție de la regulă este atunci când se atribuie un literal întreg (o valoare int) unui octet sau unei variabile scurte dacă literalul se potrivește cu intervalul variabilei.

O conversie de restrângere este întotdeauna o conversie de tip explicită.

Conversie explicită tipuri primitive

Operatorul de conversie explicită a tipului, sau mai precis, turnare a tipului, este paranteze rotunde, în interiorul căruia este indicat tipul la care are loc conversia - (tip). De exemplu:

int i = 13 ;
octet b = ( octet ) i ; // Forță conversia de la int la octet
i = ( int ) 13.456 ; // Forță conversia literalului dublu în int 13

Cel mai des se folosește turnarea de tip primitiv pentru a converti valorile în virgulă mobilă în numere întregi. în care fracțiune valorile în virgulă mobilă sunt pur și simplu eliminate(adică valoarea în virgulă mobilă este rotunjită spre zero, mai degrabă decât spre cel mai apropiat număr întreg). In esenta este luată doar partea întreagă tip real și este deja turnat la tipul întreg țintă.

Când aduceți un mai încăpător întreg tip la cel mai puțin încăpător, cei mai semnificativi biți sunt pur și simplu aruncați. În esență, aceasta este echivalentă cu operația de împărțire modulo a valorii fiind redusă cu intervalul tipului țintă (de exemplu, pentru tipul de octet este 256).

Prea mare un număr fracționar atunci când este transformat într-un număr întreg, acesta devine MAX_VALUE sau MIN_VALUE.

Prea mare dubla când adus la pluti se transformă în Float.POSITIVE_INFINITY sau Float.NEGATIVE_INFINITY.

Tabelul de mai jos este o grilă în care, pentru fiecare tip primitiv, sunt indicate tipurile în care pot fi convertite și metoda de conversie. Scrisoare Nîn tabel înseamnă că conversia nu este posibilă. Scrisoare Yînseamnă o transformare în expansiune care se realizează automat. Scrisoare CUînseamnă o transformare de îngustare care necesită o distribuție explicită. In cele din urma, Y*înseamnă o transformare automată de lărgire, în timpul căreia valoarea poate pierde unele dintre cifrele cele mai puțin semnificative. Acest lucru se poate întâmpla la conversia unui int sau long într-un float sau double. Tipurile cu virgulă mobilă au o gamă mai mare decât tipurile întregi, astfel încât int sau long pot fi reprezentate prin float sau double. Cu toate acestea, tipurile în virgulă mobilă sunt aproximări ale numerelor și este posibil să nu conțină întotdeauna atât de multe cifre semnificative în mantise ca tipurile întregi.

Extindere automată a tipului în expresii

De asemenea, merită menționat încă o dată despre promovarea (extinderea) automată a tipurilor în expresii. Am întâlnit deja acest lucru atunci când am luat în considerare tipurile de date întregi și operațiunile pe acestea, dar merită totuși amintit aici pentru a fi înțeles și mai bine și, în plus, este direct legat de acest subiect. În exemplul de mai jos semnul @ + , , * , / și așa mai departe.

Adică, toate literalele întregi din expresii, precum și tipurile octet, mic de staturaȘi char extinde la int . Dacă, așa cum este descris mai sus, expresia nu conține altele, mai multe tipuri mari date ( lung, pluti sau dubla). Prin urmare, exemplul de mai sus va provoca o eroare de compilare din cauza variabilei c are tip octet, iar expresia b+1, ca urmare a promovării automate, are tipul int.

Casting implicit de tip în expresii de atribuire mixte

Deşi aceasta sectiuneși se referă la conversia implicită (turnare) a tipurilor, am dat explicația acesteia aici, deoarece în acest caz funcționează și extinderea automată a tipului în expresii și apoi turnare implicită tipuri. Acesta este corpul de balet. Cred că exemplul de mai jos va clarifica totul. La fel ca în explicația anterioară, semnul @ înseamnă orice operator valid, de exemplu + , , * , / și așa mai departe.

Acest lucru merită explicat cu un exemplu simplu:

octet b2 = 50 ;
b2 = b2 * 2 ; // nu va compila
b2 *= 2 ; //compilează, deși este echivalent cu b2 = b2 * 2

A doua linie dată în exemplu nu se compilează din cauza extinderii automate a tipului în expresii, deoarece expresia b2*2 este de tip int, deoarece are loc extinderea automată a tipului (literalii întregi din expresie sunt întotdeauna int). A treia linie se va compila cu ușurință, deoarece castingul implicit de tip în expresia de atribuire combinată va funcționa în ea.

Boxing/unboxing - conversia tipurilor primitive în obiecte wrapper

Boxul și unboxingul este, de asemenea, un subiect destul de amplu, dar este destul de simplu.

In esenta boxul și unboxingul sunt conversii de la tipuri primitive la obiecte wrapper și înapoi.

Pentru obiectele wrapper de tipuri primitive, se aplică tot ceea ce s-a spus mai sus.

Clasele Wrapper au fost menționate în tabele atunci când s-au analizat fiecare dintre tipurile primitive. Dar atunci a fost doar o mențiune în tabel.

Deci, pentru fiecare tip primitiv există fratele său mai mare și nu este deloc primitiv, ci este o clasă reală, cu câmpuri și metode. Și pentru fiecare astfel de pereche este posibilă conversia automată.

De obicei, dacă programul are multe calcule matematice, atunci este mai bine să folosiți tipuri primitive, deoarece este mai rapid și mai economic în ceea ce privește resursele, dar uneori este nevoie să convertiți un tip primitiv într-un obiect.

Permiteți-mi să vă dau un exemplu simplu:

int i3 ;
octet b2 = 3 ;
octet meuB ;
meuB= b2;
meuB++;
b2= meuB;
i3= meuB;

Dacă nu este încă clar de ce este nevoie de acest lucru, atunci nu este înfricoșător, doar faceți un nod ca amintire.

ÎN această lecție vă vom povesti despre o mică bătaie de cap pentru programatori – tip casting. Ce este tipul de turnare? Aceasta este orice conversie de tip de date.
De exemplu:

Int b = 3;
dublu a = 1,0 * b;//conversie de tip
a = (dublu)b;//conversie de tip

Deci, puteți vedea două moduri de a schimba tipul:

  • Efectuarea unor operații asupra unui obiect
  • Conversie explicită

La ce tipuri se poate reduce? Puteți proiecta în tipuri de date care se află în aceeași ierarhie. Să presupunem că puteți converti un număr întreg într-un număr real și invers. Puteți trimite clasa Student în clasa User și așa mai departe. Evident, aruncarea unui șir la un număr este inutilă, deoarece sunt obiecte diferite. În acest caz, se folosesc de obicei operațiuni speciale.
Mai mult sau mai putin utilizatori experimentați Poate apărea următoarea întrebare:

Int b = 3;
dublu a = b;//conversie de tip 1
b = (int) a;//conversie de tip 2

De ce unui tip de date dublu i se poate atribui un tip de date int și compilatorul nu va genera o eroare, dar pentru a converti un dublu într-un int tipul trebuie specificat în mod explicit? Se dovedește că conversiile sigure, de exemplu de la int la double sau de la copil la părinte, se numesc expanding, adică permitem extinderea unui tip de date cu capacități mai mici, de exemplu un tip de date întreg, îi permitem să devină real, extinzându-se. domeniul său de aplicare. O conversie se numește extindere dacă tipul de date pe care îl trimitem include tipul de date pe care vrem să îl proiectăm pentru tipurile de bază.
Conversiile de restrângere sunt întotdeauna asociate cu o oarecare pierdere de informații, de exemplu, la conversia de la dublu la int pierdem toate valorile după virgulă zecimală, ceea ce provoacă îngrijorare pentru computer și numai indicație explicită tipul de date îl poate asigura că facem această transformare cu o minte sănătoasă și o memorie solidă.
Să ne uităm din nou la exemplul cu forme:

Forma de clasă publică (
}
clasă publică Square se extinde Forma (
}
pătrat pătrat;
Forma formei = pătrat;//transformare extinsă
pătrat = formă;//îngustare transformare

S-ar părea că atunci când ne transformăm din fiu în părinte, noi, dimpotrivă, ne îngustăm și nu ne extindem, care este motivul? Și motivul este că de fapt clasa Square conține toate informațiile clasei Shape și la transformarea din fiu în tată, pierdem doar informațiile specifice fiului, care se află în acest moment poate să nu fie important, dar atunci când transformăm din Formă în Pătrat putem obține o situație în care pur și simplu nu avem datele necesare pentru ca clasa să funcționeze, de exemplu, nu avem dimensiunea pătratului, dacă vorbim despre exemplu de mai sus.
Și la sfârșitul lecției, să ne uităm la operatorul instanceof, acesta returnează adevărat dacă obiectul are tipul dat:

If(nouă instanță Square() a Formei)(//false

Java este un limbaj de programare puternic tipizat, ceea ce înseamnă că fiecare expresie și fiecare variabilă are un strict anumit tip deja la momentul compilarii.
Tipuri de fantome
Java oferă șapte tipuri de distribuții:

  • Identic (identitate);

  • lărgirea primitivă;

  • Îngustare primitivă;

  • Referință de extindere a tipului de obiect;

  • Referință de îngustare;

  • Convertiți în șir;

  • Transformări interzise (interzise);
Să le privim separat.
Transformarea identității
Cea mai simplă este transformarea identităţii. În Java, conversia unei expresii de orice tip în exact același tip este întotdeauna validă și are succes.
Acest lucru este important pentru a putea afirma din punct de vedere teoretic că orice tip în Java poate participa la conversie, cel puțin la o conversie de identitate.
Conversie de tip primitiv (expansiune și contracție)
Pentru tipuri simple extinderea înseamnă că există o tranziție de la un tip mai puțin încăpător la unul mai încăpător. De exemplu, de la tipul octet (lungime de 1 octet) la tipul int (lungime de 4 octeți). Astfel de transformări sunt sigure în sensul că tip nou este întotdeauna garantat că va conține toate datele care au fost stocate în vechiul tip și, prin urmare, nu există nicio pierdere de date. De aceea, compilatorul îl implementează singur, neobservat de dezvoltator:

octet b=3;
int a=b;

Următoarele 19 transformări sunt de expansiune:

  • De la octet la scurt, int, long, float, double

  • De la scurt la int, long, float, double

  • De la char la int, long, float, double

  • De la int la lung, float, double

  • De la lung la plutitor, dublu

  • De la float la dublu
Vă rugăm să rețineți că nu puteți converti în char de la tipuri mai mici de sau lungime egală(octet, scurt) sau, dimpotrivă, scurtcircuitare de la char fără pierdere de date. Acest lucru se datorează faptului că char, spre deosebire de alte tipuri de numere întregi, este semnat.
Cu toate acestea, trebuie amintit că, chiar și cu extinderea, datele pot fi încă distorsionate. Aceasta este turnarea valorilor int la tip plutitorși aruncarea de valori lungi pentru a pluti sau dubla. Deși aceste tipuri fracționale găzduiesc mult numere mari, decât numerele întregi corespunzătoare, dar au mai puține cifre semnificative.
De exemplu:

a lung = 111111111111L;
float f=a;
a=(lung)f; // () aceasta este exact operația de conversie a tipului
System.out.println(a); //rezultat 111111110656

Vă rugăm să rețineți că îngustarea înseamnă că tranziția este de la un tip mai încăpător la unul mai puțin încăpător. Cu această conversie există riscul pierderii datelor. De exemplu, dacă un număr int a fost mai mare de 127, atunci când îl convertiți într-un octet, se vor pierde valorile biților mai mari decât al optulea. În Java, o astfel de conversie trebuie făcută în mod explicit, adică. Programatorul trebuie să indice în mod explicit în cod că intenționează să efectueze o astfel de conversie și este pregătit să piardă date.
Următoarele 23 de transformări se îngustează:

  • De la octet la caracter

  • De la scurt la octet, char

  • De la caracter la octet, scurt

  • De la int la octet, scurt, char

  • De la lung la octet, scurt, char, int

  • De la float la octet, short, char, int, long

  • De la dublu la octet, scurt, char, int, long, float
Când restrângeți un tip întreg la un tip întreg mai îngust, toți biții de ordin înalt care nu se încadrează în noul tip sunt pur și simplu aruncați. Nu se efectuează rotunjiri sau alte acțiuni pentru a obține un rezultat mai corect:

System.out.println((byte)383);
System.out.println((byte)384);
System.out.println((byte)-384);

Rezultatul va fi:

127
-128
-128
Se poate observa că bitul de semn nu a avut niciun efect în timpul îngustării, deoarece a fost pur și simplu aruncat - rezultatul aducerii numerelor reciproce (384, -384) s-a dovedit a fi același. În consecință, nu numai valoarea absolută exactă se poate pierde, ci și semnul mărimii.
Acest lucru este valabil și pentru char:

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

Rezultat:

-25536
Conversie tip de referință (extindere și contracție)
Conversia tipului de obiect este cel mai bine ilustrată folosind un arbore de moștenire. Să ne uităm la un mic exemplu de moștenire:

clasa Parinte(
int x;
}

clasa ChildY extinde Parent (
int y;
}

clasa ChildZ extinde Parent (
int z;
}

Fiecare clasă declară un câmp cu un nume unic. Vom considera acest câmp ca un exemplu de set de proprietăți unice inerente unui tip de obiect.
Obiectele clasei Parent au un singur câmp x, ceea ce înseamnă că numai referințele de tip Parent se pot referi la astfel de obiecte. Obiectele clasei ChildY au un câmp y și un câmp x, moștenite de la clasa Părinte. Prin urmare, astfel de obiecte pot fi indicate prin referințe de tip ChildY sau Parent. Exemplu:

Părinte p = nou CopilY();

Rețineți că o astfel de referință p poate accesa doar câmpul x al obiectului creat. Câmpul y nu este disponibil deoarece compilatorul, la verificarea validității expresiei p.y, nu poate prezice că referința p va indica un obiect de tip ChildY în timpul execuției. Analizează doar tipul variabilei în sine și este declarată ca Parent, dar această clasă nu are câmpul y, ceea ce va cauza o eroare de compilare.
În mod similar, obiectele clasei ChildZ au un câmp z și un câmp x derivat din clasa Părinte. Aceasta înseamnă că astfel de obiecte pot fi indicate prin link-uri precum ChildZ și Parent.
Astfel, referințele de tip Parent pot indica un obiect din oricare dintre cele trei tipuri luate în considerare, dar referințele de tip ChildY și ChildZ pot indica doar obiecte de exact același tip. Acum putem trece la conversia tipurilor de referință pe baza acestui arbore de moștenire.
Extinderea înseamnă trecerea de la un tip mai specific la un tip mai puțin specific, adică. trecerea de la copii la părinți. Similar cu cazul tipurilor primitive, această tranziție este făcută chiar de JVM dacă este necesar și este „invizibilă” pentru dezvoltator, adică nu necesită conversii speciale.

Părinte p1=copil nou Y();
Părinte p2=nou CopilZ();

Pe ambele linii variabile de tip Părintelui i se atribuie o valoare de alt tip, ceea ce înseamnă că are loc o conversie. Deoarece aceasta este o extensie, se face automat și are întotdeauna succes.
Trebuie remarcat faptul că în timpul unei astfel de transformări nu se întâmplă nimic obiectului în sine. Chiar dacă, de exemplu, câmpul y al clasei ChildY nu mai este disponibil, asta nu înseamnă că a dispărut. O astfel de schimbare semnificativă a obiectului nu este posibilă. A fost derivat din clasa ChildY și își păstrează toate proprietățile. S-a schimbat doar tipul de link prin care este accesat obiectul.
Tranziția inversă, adică deplasarea în jos a arborelui moștenire către moștenitori, este o îngustare. De exemplu, în acest caz, trecerea de la o referință de tip Parent, care se poate referi la obiecte din trei clase, la o referință de tip ChildY, care se poate referi doar la una dintre cele trei clase, este evident o îngustare. O astfel de tranziție ar putea să nu fie posibilă. Dacă o referință de tip Parent se referă la un obiect de tip Parent sau ChildZ, atunci o tranziție la ChildY nu este posibilă, deoarece în ambele cazuri obiectul nu are un câmp y, care este declarat în clasa ChildY. Prin urmare, atunci când se îngustează, designerul trebuie să indice în mod explicit că este necesar să încerce o astfel de transformare. JVM-ul va verifica dacă tranziția este corectă în timpul execuției. Dacă este posibil, conversia va fi efectuată. Dacă nu, va apărea o eroare (de obicei o ClassCastException).

Părinte p=nou CopilY();
ChildY cy = (ChildY)p; //dreapta
Părinte p2=nou CopilZ();
ChildY cy2 = (ChildY)p2; //eroare

Pentru a verifica dacă tranziția dorită este posibilă, puteți utiliza operatorul instanceof:

Părinte p=nou CopilY();
dacă (p exemplu de ChildY) (
ChildY cy = (ChildY)p;
}

Părinte p2=nou CopilZ();
dacă (p2 instanță de ChildY) (
ChildY cy = (ChildY)p2;
}

Parent p3=new Parent();
dacă (p3 instanță de ChildY) (
ChildY cy = (ChildY)p3;
}

ÎN în acest exemplu nu vor apărea erori. Prima transformare este posibilă și se va realiza. În al doilea și al treilea caz, condițiile declarațiilor if nu vor funcționa și, prin urmare, nu va exista o tranziție incorectă.
Conversie în șir
Orice tip poate fi turnat într-un șir, de ex. a copia clasa String. Această transformare este excepțională datorită faptului că acoperă absolut toate tipurile.
Diferitele tipuri sunt convertite în șir, după cum urmează:

  • Tipurile numerice sunt scrise în forma text fără pierderea acurateței prezentării. Mai întâi, o instanță a clasei „wrapper” corespunzătoare este generată pe baza valorii primitive, apoi este apelată metoda sa toString(). Dar, deoarece aceste acțiuni sunt invizibile din exterior, JVM-ul le optimizează și convertește valorile primitive în text direct.

  • Valorile booleene sunt turnate în șirul „adevărat” sau „fals”, în funcție de valoare.

  • Pentru valorile obiectului, este apelată metoda toString(). Dacă metoda returnează null, rezultatul va fi șirul „null”.

  • Pentru o valoare nulă, este generat șirul „null”.
Transformări interzise
Nu sunt permise toate tranzițiile între tipurile arbitrare. De exemplu, conversiile interzise includ: tranzițiile de la orice tip de referință la un tip primitiv și invers (cu excepția conversiei într-un șir), booleanul poate fi turnat numai în acest tip sau într-un șir. În plus, este imposibil să aduceți clasele situate pe ramurile adiacente ale arborelui moștenire una la alta. În exemplul folosit pentru a ilustra tipurile de referință, trecerea de la ChildY la ChildZ este interzisă.
Această listă de transformări interzise nu se termină aici. Este destul de larg și în același timp toate opțiunile sunt destul de evidente, așa că nu vor fi discutate în detaliu. Cei care doresc pot primi informatii complete din caietul de sarcini.
Desigur, încercarea de a efectua o conversie ilegală va provoca o eroare.

Utilizarea gipsurilor
Situațiile de utilizare a conversiei de tip pot fi grupate după cum urmează:

  • Atribuirea de valori variabilelor (atribuire). Nu toate tranzițiile sunt permise în timpul acestei transformări - restricțiile sunt alese astfel încât să nu poată apărea o excepție.

  • Apel de metodă. Această conversie se aplică argumentelor metodei sau constructorului numit. O astfel de distribuție nu produce niciodată erori. Turnarea se efectuează și atunci când valoarea metodei este returnată.

  • Casting explicit. În acest caz, este indicat în mod explicit la ce tip trebuie turnată valoarea inițială.

  • Operatorul de concatenare se convertește într-un șir de argumente.

  • Expansiunea numerică. Operații numerice poate necesita schimbarea tipului argumentului (argumentelor). Această conversie are un nume special - extins, deoarece alegerea tipului țintă poate depinde nu numai de valoarea inițială, ci și de al doilea argument al operației.
Sarcina #8
Adaugă la proiectul tău utilizarea casting-ului pentru ierarhia clasei.

Vorbitorul precedent a descris destul de complet conversie descendentă, dar concluzia (în opinia mea) necesită o explicație suplimentară, deoarece întrebarea este foarte populară și interesantă.

Cum funcționează turnarea de tip explicit

Exemplul dvs. arată o transformare ascendentă ( Upcasting):

List coll = new ArrayList();

Este tradus în rusă după cum urmează: creați o cioară, ca o pasăre. Creați o matrice dinamică, ca o foaie. În majoritatea situațiilor, o conversie ascendentă este complet inutilă.
Cu toate acestea, tip casting funcționează în interviuri atunci când vi se pun întrebări despre moștenire. De exemplu, site-ul web quizful.net conține în general o mulțime de întrebări despre tipul de turnare. Prin urmare, voi explica caracteristicile pe care le cunosc.

Deci, în exemplul de mai sus, am creat un obiect de tip ArrayList și o referință de tip List. Amintiți-vă axiomele pentru această metodă:

1. Link-ul poate fi îndreptat către orice părinte. Chiar și cu foarte mult timp în urmă. Adică, puteți arunca o referință collare chiar și la tipul Object. Compilatorul va omite orice referință la o clasă părinte, sau părinte-părinte, sau părinte-părinte... părinte

2. La accesarea unui câmp, câmpul de referință este întotdeauna returnat, nu câmpul obiect. Dacă nu există un astfel de câmp în clasa de referință, va exista o eroare de compilare.

Clasa A( int x = 2; // Câmpul părintelui) Clasa B se extinde pe A ( int x = 3; // Câmpul care ar trebui să se suprapună pe părintele int y = 5; // Câmpul care nu este în clasa părinte. ) Test de clasă ( public static void main(String args) ( A ab = new B(); //Conversie ascendentă System.out.println("Int x = " + ab.x); ) )

Va reveni Int x = 2 . Dacă încercați să accesați un câmp al unui obiect:

System.out.println("Int y = " + ab.y); //Eroare de compilare

Compilatorul tău va spune că te înșeli, deoarece nu vede un astfel de câmp în link (A ab). Toate cele de mai sus rămân valabile chiar dacă marcați câmpurile cu modificatori statici.

3. Apelarea unei metode non-statice: în acest caz, metoda obiectului va fi returnată. Dar atunci când accesați o metodă statică, returnează metoda de referință.

Clasa D( public void doSome())( //Metoda nonstatica System.out.println("Nonstatic doSome din D"); ) public static void Action())( //Metoda statica System.out.println("static Action din D "); ) ) public class Okey extinde D( public void doSome())( System.out.println("doSome din Okey"); ) public static void Action())( System.out.println("static Action from Okey" ); ) public static void main(String args) ( D o=new Okey(); o.doSome(); //Din clasa Okey o.Action(); //Din clasa D ) )

DoSome nonstatic de la Okey

Acțiune statică din D

Soluția este simplă, o metodă non-statică este o metodă obiect, o metodă statică este o metodă de clasă. Când numim o metodă non-statică, compilatorul înțelege acest lucru: zboară ca o cioară. Când numim static - la propriu, zboară ca o pasăre.

4. Dacă există un apel la o metodă care este descrisă în clasa obiectului, dar nu este descrisă în clasa de referință, va apărea o eroare de compilare. Deoarece metoda este numită prin referință:

Clasa A () Clasa B extinde A ( void someMethod())(); public static void main(String args) (A ab = new B(); ab.someMethod(); //Eroare de compilare. ) )

5. Constructorul de obiecte (atunci când este creat cu noua comandă) funcționează la fel ca și cum ai oferi un link către clasa ta.

Acest articol:

  • scris de echipa. Sperăm că vă va fi de folos. Lectura placuta!
  • acesta este unul dintre articolele noastre

Conversia tipului este un subiect care poate părea descurajant pentru cei care sunt începători în programarea Java. Cu toate acestea, vă asigurăm că totul este de fapt simplu. Principalul lucru este să înțelegi ce legi guvernează interacțiunea dintre variabile și rețineți acest lucru atunci când scrieți programe. Deci, hai să ne dăm seama.

Există 2 tipuri de transformări în Java - imaginea vă va ajuta:

Amintiți-vă că întregul „Univers Java” este format din:

  • tipuri primitive (byte, short, int, long, char, float, double, boolean)
  • obiecte

În acest articol noi:

  • luați în considerare conversia tipului pentru tipurile de variabile primitive
  • conversia obiectelor (String, Scanner etc.) nu este luată în considerare în acest articol, deoarece obiectelor se întâmplă o „magie” separată - acesta este un subiect pentru un articol separat.
Conversie automată

Ei bine, să încercăm să ne dăm seama ce este „conversia automată”.

Amintiți-vă, când ne-am uitat la tipurile de variabile (în articol), am spus asta o variabilă este un fel de „container” , care poate stoca o valoare pentru utilizare ulterioară în program. Am mai vorbit despre faptul că fiecare tip de variabilă are propriul său interval de valori valide și cantitatea de memorie pe care o ocupă. Iată semnul unde a fost scris totul:

Deci, la asta ajungem de fapt. În plus, nu este doar faptul că ți s-au oferit intervale de valori acceptabile și cantitatea de memorie ocupată :)

Să comparăm, de exemplu:

1. octet și scurt. byte are un interval mai mic de valori valide decât scurt. Adică, byte este ca o casetă mai mică, iar scurtă este o casetă mai mare. Si asta inseamnă putem pune octetul pe scurt.

2. octet și int. byte are un interval mai mic de valori valide decât int. Adică, byte este ca o casetă mai mică, iar int este ca o casetă mai mare. Si asta inseamnă putem pune octet în int.

3. int şi lung. int are un interval mai mic de valori valide decât long. Adică, int este ca o cutie mai mică, iar long este ca o cutie mai mare. Si asta inseamnă putem pune int în lung.

Acesta este un exemplu de conversie automată. Acest lucru poate fi reprezentat schematic sub forma unei imagini ca aceasta:

Să vedem cum funcționează acest lucru în practică.

Exemplul nr. 1

Codul nr. 1 - dacă rulați acest cod pe computer,

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

test de clasa(

octet a = 15 ;

octet b = a ;

Codul nr. 2 - dacă rulați acest cod pe computer, numărul 15 va fi afișat în consolă

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

test de clasa(

public static void main (Argumente șir) (

octet a = 15 ;

int b = a ;

Sistem. afară . println(b);

Eeyore? Crezi ca ori același număr a fost scos pe consolă, iar codul nr. 1 diferă de codul nr. 2 doar prin tipul de variabilă b , atunci nu există nicio diferență între ele? E nu este adevarat.

Codul nr.2 conţine automatconversie de tip , dar în codul nr. 1 - nu:

Deși numărul este, în principiu, același, acum este în b O un container mai mare care ocupă mai mult spațiu pe disc. În acest caz, JVM funcționează conversii automate Pentru dumneavoastră. Ea știe asta int mai mult decât octet .

Distribuție

Este o problemă diferită dacă încercați să transferați ceva dintr-un recipient mai mare într-unul mai mic.

Poate știți că containerul mai mare conține ceva care poate încăpea în cel mic - dar JVM-ul nu știe despre acest lucru și încearcă să vă protejeze de erori.

Prin urmare, trebuie să „spuneți clar” că situația este sub control:

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

test de clasa(

public static void main (Argumente șir) (

int a = 0 ;

lung b = 15;

a = (int) b;

Aici am adăugat (int) inainte de b. Dacă variabila A a fost, de exemplu, ca octet, între paranteze ar fi (octet) . Formula generala arata asa:

Ea spune „face de (mai) sens b o variabilă de tipul de care am nevoie (țintă) int ".

Dacă ceva a mers prost.

Înainte de aceasta, am abordat situațiile presupunând că știm exact ce facem. Dar dacă încerci să pui ceva într-un recipient care nu se potrivește acolo?

Se pare că doar ceea ce „se potrivește” acolo va rămâne în recipient. De exemplu, pentru numerele cu virgulă mobilă, partea fracțională va fi „tăiată”:

//exemplu 1 test de clasă ( public static void main(String args) ( double a=11.2345; int b=(int)a; System.out.println(b); // consola va afișa numărul 11 ​​) )

//exemplul 1

test de clasa(

public static void main (Argumente șir) (

dublu a = 11,2345;

int b = (int ) a ;

Sistem. afară . println(b); // consola va afișa numărul 11

Trebuie să ne amintim că partea fracționată nu rotunjite, A aruncat.

Ce se întâmplă dacă încercăm să plasăm un număr care se află în afara intervalului permis? De exemplu, dacă puneți numărul 128 în octet (interval de octeți de la -128 la 127)? Crezi că vom primi 1? Nu. Obținem -128:

Class Test ( public static void main(String args) ( double a=128; byte b=(byte)a; System.out.println(b); // vom vedea -128 în consolă) )

Valoarea unei variabile cu o astfel de transformare poate fi calculată, dar scopul programatorului este de a evita o situație în care valoarea depășește limitele admise, deoarece acest lucru poate duce la defecțiune programe.

Sarcini:
  1. Scrieți în mod constant în compilator conversiile tuturor tipurilor primitive între ele, inclusiv caracterul și tipurile. Faceți un tabel ca acesta:
octet mic de statura char int lung pluti dubla boolean
octet
mic de statura
char
int
Lung
Pluti
dubla
boolean

La intersecție scrieți: a - dacă conversia are loc automat, on - dacă trebuie să utilizați o conversie explicită, x - dacă conversia este imposibilă.

* se numește turnarea unui tip în sine identic– nu este necesară înregistrarea acestuia

  1. Priviți din nou ce dimensiune are fiecare tip primitiv. Încercați să faceți o diagramă care să arate ce tipuri merg unde. Desenați săgețile etichetate „transformare extinsă” și „transformare restrânsă”.
Întrebări

În timpul unui interviu pentru postul de Junior Java Developer, s-ar putea să fii întrebat:

Ce știți despre conversia tipurilor de date primitive, există pierderi de date, este posibil să convertiți un tip boolean?

Încercați să răspundeți la întrebare.

Să rezumam:
  • Dacă „puneți” conținutul unui container mai mic într-un container mai mare, conversia are loc automat și nu ar trebui să apară erori.
  • Dacă este nevoie să puneți „o valoare dintr-un container mai mare într-unul mai mic”, trebuie să fiți atenți și să utilizați tipul de turnare explicit.
  • Când turnați tipurile float sau dublu la întreg, partea fracțională nu este rotunjită, ci pur și simplu aruncată.
  • Tipul boolean nu poate fi convertit la niciun tip.
  • Tipul de caractere este transformat în tipuri numerice, ca un cod de caractere în sistemul UNICODE.
  • Dacă numărul este mai mare decât containerul său, rezultatul va fi imprevizibil.

Acest articol descrie doar o parte a materialului pe tema turnării tipului. Există și modele de tip obiect, turnări pe un șir (la urma urmei, orice poate fi scris într-un șir, nu?) și promovarea automată a tipului în expresii.

Sperăm că articolul nostru v-a fost de folos. Există, de asemenea, posibilitatea de a vă înscrie la cursurile noastre Java din Kiev. Predăm de la zero. Informatii detaliateÎl puteți găsi pe site-ul nostru.


Cele mai bune articole pe această temă