Si të konfiguroni telefonat inteligjentë dhe PC. Portali informativ

Hedhja e një vargu në një numër java. Konvertimi i vargjeve Java në vlera të llojeve të tjera

Kjo është një temë mjaft e madhe, por ne do të përpiqemi ta mbulojmë atë sa më plotësisht dhe kompakt të jetë e mundur. Pjesërisht, ne kemi prekur tashmë këtë temë kur shikuam llojet primitive Java.

Java lejon konvertimet midis vlerave të numrave të plotë dhe atyre të pikës lundruese. Ju gjithashtu mund të konvertoni vlerat e numrave të plotë dhe të pikës lundruese në vlera char dhe anasjelltas, sepse çdo karakter korrespondon me një shifër Unicode. Në fakt, tipi boolean është i vetmi lloj primitiv në Java që nuk mund të konvertohet në një lloj tjetër primitiv. Gjithashtu, çdo lloj tjetër primitiv nuk mund të konvertohet në boolean.

Konvertimi i tipit në Java është dy llojesh: të nënkuptuar Dhe eksplicite.

Konvertimi i tipit implicit ekzekutohet nëse plotësohen kushtet e mëposhtme:

  1. Të dy llojet janë të pajtueshme
  2. Gjatësia lloji i synuar më e madhe ose e barabartë me gjatësinë e tipit origjinal

Në të gjitha rastet e tjera, përdorni konvertimi i tipit eksplicit.

Ekzistojnë gjithashtu dy lloje të transformimeve:

  1. Zgjerimi i konvertimit
  2. Konvertimi ngushtues

Zgjerimi i transformimit ( shndërrimi në zgjerim) ndodh nëse një vlerë e një lloji konvertohet në një lloj më të gjerë, me një diapazon më të madh vlerat e lejuara. Java kryen konvertime zgjeruese automatikisht, për shembull, nëse caktoni një literal të tipit int një ndryshoreje të tipit double, ose një ndryshore të tipit char në një variabël të tipit int. Një konvertim i nënkuptuar është gjithmonë i një lloji të zgjeruar.

Por mund të ketë disa grabujë të vogla këtu. Për shembull, nëse një vlerë int konvertohet në një vlerë float. Dhe vlera e int në paraqitjen binare është më e madhe se 23 pjesë të rëndësishme, atëherë është e mundur një humbje e saktësisë, pasi tipi float ka 23 bit për pjesën e plotë. Të gjitha pjesët e ulëta vlerat int që nuk përshtaten në mantisa 23 bit të një float do të hidhen poshtë, kështu që megjithëse rendi i numrave ruhet, saktësia humbet. E njëjta gjë vlen edhe për transformimin lloji i gjatë për të shtypur dyfish.

Zgjerimi i konvertimit të tipit Java mund të përshkruhet gjithashtu si kjo:

vija të forta tregojnë konvertimet e kryera pa humbje të të dhënave. Vijat e ndërprera tregojnë se mund të ndodhë një humbje e saktësisë gjatë konvertimit.

Vlen të shpjegohet pak pse, për shembull, lloji i bajtit nuk konvertohet automatikisht (në mënyrë implicite) në llojin char, megjithëse lloji i bajtit ka një gjerësi prej 8 bit, dhe lloji char është 16, e njëjta gjë vlen edhe për konvertimin. të tipit të shkurtër të char. Kjo ndodh sepse byte dhe short janë tipe të dhënash të nënshkruara, ndërsa char është i panënshkruar. Prandaj, në këtë rast ju duhet të përdorni një cast eksplicit, sepse duhet t'i tregoni në mënyrë eksplicite kompajlerit se ju e dini se çfarë dëshironi dhe si do të trajtohet biti i shenjës së bajtit dhe tipave të shkurtër kur konvertohet në llojin char.

Sjellja e një vlere char është në shumicën e rasteve e njëjtë me atë të një vlere të tipit të plotë, kështu që një vlerë char mund të përdoret kudo ku kërkohet një vlerë int ose long. Kujtoni, megjithatë, se lloji char është i panënshkruar, kështu që ai sillet ndryshe nga tipi i shkurtër, edhe pse diapazoni i të dy llojeve është 16 bit.

shkurt s = ( shkurt ) 0xffff; // Këto bit paraqesin numrin -1
karakter c = "\ffff"; // Të njëjtat bit përfaqësojnë një karakter unicode
ndër i1 = s; // Shndërrimi nga short në int jep -1
ndër i2 = c; // Shndërrimi i char në int jep 65535

Transformimi ngushtues ( ngushtimi i konvertimit) ndodh nëse vlera konvertohet në një vlerë të një lloji, diapazoni i së cilës nuk është më i gjerë se vlera origjinale. Ngushtimi i konvertimeve nuk është gjithmonë i sigurt: për shembull, konvertimi i vlerës së numrit të plotë 13 në bajt ka kuptim, por konvertimi i 13000 në bajt është i paarsyeshëm sepse bajt mund të ruajë vetëm numra midis -128 dhe 127. Meqenëse të dhënat mund të humbasin gjatë konvertimit ngushtues, Përpiluesi Java kundërshton çdo konvertim të tillë, edhe nëse vlera që konvertohet bie brenda intervalit më të ngushtë të llojit të specifikuar:

ndër i = 13 ;
bajt b = i ; // Përpiluesi nuk do ta zgjidhë këtë shprehje

Përjashtimi i vetëm nga rregulli është caktimi i një literali të plotë (një vlerë int) në një bajt ose ndryshore të shkurtër nëse literali përputhet me diapazonin e ndryshores.

Një konvertim ngushtues është gjithmonë një konvertim i qartë i tipit..

Konvertimi i qartë lloje primitive

Operatori eksplicit i konvertimit të tipit, ose më konkretisht tipi i hedhjes, është kllapa të rrumbullakëta, brenda së cilës tregohet lloji në të cilin bëhet konvertimi - (lloji). Për shembull:

ndër i = 13 ;
bajt b = ( bajt ) i ; // Konvertimi i detyruar nga int në bajt
i = ( ndër ) 13.456 ; // Shndërrimi i detyruar i tipit të dyfishtë literal në int 13

Më së shpeshti përdoret derdhja e tipit primitiv për të kthyer vlerat e pikave lundruese në numra të plotë. ku pjesë thyesore Vlerat e pikës lundruese thjesht hidhen poshtë(d.m.th., vlera e pikës lundruese rrumbullakoset drejt zeros, jo drejt numrit të plotë më të afërt). Në thelb merrni vetëm pjesën e plotë lloji real dhe tashmë është hedhur në llojin e numrit të plotë të synuar.

Kur sjell një më të gjerë tip numër i plotë në një më pak të gjerë, pjesët e larta thjesht hidhen. Kjo është në thelb e njëjtë me ndarjen e modulit të vlerës së transmetimit me diapazonin e llojit të synuar (për shembull, 256 për bajt).

Shumë e madhe një numër thyesor kur transferohet në një numër të plotë, ai bëhet MAX_VALUE ose MIN_VALUE.

Shumë e madhe dyfishtë kur sillen në noton bëhet Float.POSITIVE_INFINITY ose Float.NEGATIVE_INFINITY.

Tabela më poshtë është një rrjet, ku për çdo lloj primitiv tregohen llojet në të cilat mund të konvertohen dhe mënyra e konvertimit. Letër N në tabelë do të thotë se konvertimi nuk është i mundur. Letër Y nënkupton një konvertim të zgjeruar që bëhet automatikisht. Letër NGA nënkupton një konvertim ngushtues që kërkon një cast të qartë. Së fundi, Y* do të thotë konvertim automatik i zgjerimit, gjatë të cilit vlera mund të humbasë disa nga bitet më pak të rëndësishme. Kjo mund të ndodhë kur konvertoni një int ose long në një float ose double. Llojet me pikë lundruese kanë një gamë më të madhe se llojet e numrave të plotë, kështu që një int ose e gjatë mund të përfaqësohet si një float ose dyfish. Megjithatë, llojet me pikë lundruese janë numra të përafërt dhe mund të mos përmbajnë gjithmonë aq shifra të rëndësishme në mantissa sa llojet e plotë.

Zgjerimi automatik i tipit në shprehje

Vlen të përmendet edhe një herë promovimi (zgjerimi) automatik i llojeve në shprehje. Ne e kemi hasur tashmë këtë kur kemi konsideruar llojet e të dhënave të numrave të plotë dhe operacionet mbi to, por ia vlen të kujtojmë këtu, në mënyrë që ta kuptoni edhe më mirë dhe përveç kësaj, lidhet drejtpërdrejt me këtë temë. Në shembullin e mëposhtëm, shenja @ + , , * , / etj.

Kjo do të thotë, të gjitha literalet e numrave të plotë në shprehje, si dhe llojet bajt, shkurt Dhe karakter zgjerohet në ndër . Nëse, siç përshkruhet më sipër, shprehja nuk përmban të tjera, më shumë lloje të mëdha te dhena ( gjatë, noton ose dyfishtë). Prandaj, shembulli i mësipërm do të shkaktojë një gabim përpilimi sepse ndryshorja c ka lloj bajt, dhe shprehja b+1, si rezultat i promovimit automatik, është e tipit ndër.

Hedhja e tipit implicit në shprehjet e detyrave të kombinuara

edhe pse këtë seksion dhe i referohet konvertimit të tipit të nënkuptuar (casting), shpjegimin e kemi dhënë këtu, pasi në këtë rast funksionon edhe zgjerimi automatik i tipit në shprehje, dhe më pas cast i nënkuptuar llojet. Këtu është një trup i baletit. Shembulli i mëposhtëm do ta bëjë të qartë, mendoj. Si në shpjegimin e mëparshëm, shenja @ nënkupton çdo operator të vlefshëm, për shembull + , , * , / etj.

Kjo duhet të shpjegohet me një shembull të thjeshtë:

bajt b2 = 50 ;
b2 = b2 * 2 ; // nuk do të përpilohet
b2 *= 2 ; //përpilon, edhe pse ekuivalente me b2 = b2 * 2

Rreshti i dytë në shembull nuk do të përpilohet për shkak të zgjerimit automatik të tipit në shprehje, pasi shprehja b2*2 ka llojin int, pasi ndodh zgjerimi i tipit automatik (literalet e plotë në shprehje janë gjithmonë int). Rreshti i tretë do të përpilohet lehtësisht, meqenëse hedhja e tipit të nënkuptuar në shprehjen e detyrës së kombinuar do të funksionojë në të.

Boxing/unboxing - konvertimi i llojeve primitive në objekte mbështjellëse

Boksi dhe çboksimi është gjithashtu një temë mjaft e madhe, por është mjaft e thjeshtë.

Në thelb boksi dhe çboksimi është shndërrimi i llojeve primitive në objekte mbështjellëse dhe anasjelltas.

Për objektet mbështjellëse të llojeve primitive, vlen gjithçka që u tha më sipër.

Klasat e mbështjellësit janë përmendur në tabela, kur analizohet secili prej llojeve primitive. Por atëherë ishte vetëm një përmendje në tabelë.

Pra, për çdo lloj primitiv ka vëllain e tij më të madh, dhe ai nuk është fare primitiv, por është një klasë e vërtetë, me fusha dhe metoda. Dhe për çdo çift të tillë, konvertimi automatik është i mundur.

Zakonisht, nëse programi ka shumë llogaritjet matematikore, është më mirë të përdoren lloje primitive, pasi është më i shpejtë dhe më ekonomik për sa i përket burimeve, por ndonjëherë ka nevojë të konvertohet një lloj primitiv në një objekt.

Unë do të jap një shembull të thjeshtë:

ndër i3 ;
bajt b2 = 3 ;
byte myB ;
myB= b2;
myB++;
b2= myB;
i3= myB;

Nëse nuk është ende e qartë pse është e nevojshme kjo, atëherë nuk është e frikshme, thjesht lidhni një nyjë si një kujtim.

këtë mësim ne do t'ju tregojmë për një dhimbje koke të vogël për programuesit - tip casting. Çfarë është derdhja e tipit? Ky është çdo konvertim i llojit të të dhënave.
Për shembull:

int b = 3;
dyfishi a = 1.0 * b;//konvertimi i tipit
a = (dyfish)b;//konvertimi i llojit

Kështu, mund të shihni dy mënyra për të ndryshuar llojin:

  • Kryerja e disa veprimeve në një objekt
  • Konvertimi i qartë

Cilat lloje mund të hidhen? Ju mund të transmetoni në llojet e të dhënave që janë në të njëjtën hierarki. Supozoni se mund të konvertoni një numër të plotë në një numër real dhe anasjelltas. Ju mund ta transmetoni klasën Student në klasën Përdorues, e kështu me radhë. Është e qartë se është e kotë t'i hedhësh një varg një numri, pasi këto janë objekte të ndryshme. Në këtë rast, zakonisht përdoren operacione speciale.
Pak a shume përdoruesit me përvojë mund të lindë pyetja e mëposhtme:

int b = 3;
dyfishi a = b;//konvertimi i tipit 1
b = (int) a; // konvertimi i tipit 2

Pse tipit të të dhënave të dyfishta mund t'i caktohet lloji i të dhënave int dhe përpiluesi nuk do të gjenerojë një gabim, por për të hedhur double në int, duhet të specifikoni në mënyrë eksplicite llojin? Rezulton se konvertimet e sigurta, p.sh. nga int në dyfish ose nga djali në prind, quhen zgjerime, dmth japim një lloj të dhënash me aftësi më të ulëta për t'u zgjeruar, për shembull, një lloj të dhënash integer, japim mundësinë të bëhet real. , duke zgjeruar shtrirjen e saj. Thuhet se një konvertim po zgjerohet nëse lloji i të dhënave që ne po transmetojmë përfshin llojin e të dhënave që duam të transmetojmë për llojet bazë.
Konvertimet e ngushtuara shoqërohen gjithmonë me disa humbje informacioni, për shembull, kur konvertojmë nga dyfishi në int, ne humbim të gjitha vlerat pas pikës dhjetore, gjë që shkakton shqetësim për kompjuterin dhe vetëm tregues i qartë tipi i të dhënave mund ta sigurojë atë se ne po e bëjmë këtë konvertim me mirëbesim dhe me kujtesë të fortë.
Shqyrtoni përsëri shembullin me forma:

Forma e klasës publike (
}
Klasa publike Sheshi zgjeron formën (
}
katror katror;
Forma e formës = katror;//zgjerimi i transformimeve
katror = trajtë;//shndërrime ngushtuese

Duket se duke u shndërruar nga djali në prind, përkundrazi, po ngushtohemi, dhe nuk po zgjerojmë, cila është arsyeja? Dhe arsyeja është se në fakt klasa Square përmban të gjithë informacionin e klasës Shape dhe duke u shndërruar nga djali në baba, ne humbasim vetëm informacionin specifik për djalin, i cili në ky moment mund të mos jetë e rëndësishme, por konvertimi nga Shape në Shesh mund të arrijmë një situatë të tillë që thjesht të mos kemi të dhënat e nevojshme që klasa të funksionojë, për shembull, nuk kemi madhësinë e katrorit, nëse flasim për shembull më sipër.
Dhe në fund të mësimit, merrni parasysh shembullin e operatorit, ai kthehet true nëse objekti ka një lloj të caktuar:

If(new Square() instance of Shape)(//false

Java është një gjuhë programimi e shtypur fort, që do të thotë se çdo shprehje dhe çdo variabël ka një të shtypur fort lloj i caktuar tashmë në momentin e përpilimit.
Llojet e kallëpeve
Java ofron shtatë lloje kastesh:

  • Identiteti;

  • Zgjerimi i një tipi primitiv (primitiv zgjerues);

  • tip primitiv ngushtues (ngushtues primitiv);

  • Zgjerimi i llojit të objektit (referenca e zgjerimit);

  • Ngushtimi i llojit të objektit (referenca e ngushtimit);

  • Konverto në varg (String);

  • Shndërrime të ndaluara (të ndaluara);
Le t'i shqyrtojmë ato veçmas.
Transformimi i identitetit
Më e thjeshta është transformimi i identitetit. Në Java, konvertimi i një shprehjeje të çdo lloji në të njëjtin lloj është gjithmonë i ligjshëm dhe ka sukses.
Kjo është e rëndësishme në mënyrë që të mund të argumentohet teorikisht se çdo lloj në Java mund të marrë pjesë në një konvertim, edhe nëse është identik.
Konvertimi primitiv i tipit (zgjerimi dhe ngushtimi)
Për lloje të thjeshta zgjerim do të thotë se bëhet një kalim nga një lloj më pak i gjerë në një më të gjerë. Për shembull, nga lloji byte (gjatësia 1 bajt) në lloji int (gjatësia 4 byte). Transformime të tilla janë të sigurta në kuptimin që lloj i riështë gjithmonë e garantuar të përmbajë të gjitha të dhënat që janë ruajtur në llojin e vjetër, dhe kështu nuk ndodh humbje e të dhënave. Kjo është arsyeja pse përpiluesi e zbaton atë vetë, në mënyrë të padukshme për zhvilluesin:

byteb=3;
int a=b;

19 transformimet e mëposhtme po zgjerohen:

  • Nga bajt në shkurt, int, i gjatë, float, dyfish

  • Nga i shkurtër në int, i gjatë, float, dyfish

  • Nga char në int, e gjatë, float, dyfish

  • Nga int në të gjatë, float, dyfish

  • Nga e gjata te noton, dyfish

  • float për të dyfishuar
Vini re se nuk mund të konvertoheni në char nga llojet më të vogla se ose gjatësi të barabartë(byte, short) ose anasjelltas në shkurt nga char pa humbje të të dhënave. Kjo për faktin se char, ndryshe nga llojet e tjera të numrave të plotë, është i nënshkruar.
Sidoqoftë, duhet mbajtur mend se edhe me zgjerim, të dhënat ende mund të shtrembërohen. Kjo po hedh vlera int tek tip notues dhe vlerat e derdhjes të tipit të gjatë në tip float ose dyfish. Edhe pse këto lloje të pjesshme mund të strehojnë shumë numra të mëdhenj se numrat e plotë përkatës, por ato kanë më pak shifra të rëndësishme.
Për shembull:

e gjatë a = 111111111111L;
float f=a;
a=(e gjate)f; // () është vetëm një operacion i konvertimit të tipit
System.out.println(a); //rezultati 111111110656

Kushtojini vëmendje - ngushtimi - do të thotë që kalimi kryhet nga një lloj më i gjerë në një më pak të gjerë. Me një konvertim të tillë, ekziston rreziku i humbjes së të dhënave. Për shembull, nëse një int ishte më e madhe se 127, atëherë kur të hidhet në bajt, vlerat e bitit më të vjetra se e teta do të humbasin. Në Java, një konvertim i tillë duhet të bëhet në mënyrë eksplicite, d.m.th. programuesi në kod duhet të tregojë në mënyrë eksplicite se ai synon të kryejë një konvertim të tillë dhe është gati të humbasë të dhënat.
23 transformimet e mëposhtme po ngushtohen:

  • nga bajt në karakter

  • Nga shkurt në bajt, char

  • Nga karakteri në bajt, shkurt

  • Nga int në byte, i shkurtër, char

  • Nga e gjata në bajt, e shkurtër, char, int

  • Nga float në bajt, i shkurtër, char, int, i gjatë

  • Nga dyfishi në bajt, i shkurtër, char, int, i gjatë, float
Kur ngushtoni një tip numër të plotë në një tip numër të plotë më të ngushtë, të gjithë bitat e rendit të lartë që nuk përshtaten në llojin e ri thjesht hidhen. Asnjë rrumbullakim ose veprime të tjera nuk kryhen për të marrë një rezultat më të saktë:

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

Rezultati do të jetë:

127
-128
-128
Mund të shihet se biti i shenjës nuk pati ndonjë efekt gjatë ngushtimit, pasi thjesht u hodh - rezultati i hedhjes së numrave reciprokë (384, -384) doli të ishte i njëjtë. Rrjedhimisht, mund të humbasë jo vetëm vlera e saktë absolute, por edhe shenja e sasisë.
Kjo është e vërtetë edhe për karakterin:

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

Rezultati:

-25536
Konvertimi i llojit të referencës (zgjerimi dhe ngushtimi)
Konvertimi i llojit të objektit ilustrohet më së miri duke përdorur një pemë trashëgimore. Konsideroni një shembull të vogël të trashëgimisë:

prindi i klasës(
intx;
}

klasa ChildY zgjat prind(
int y;
}

klasa ChildZ zgjeron prindin(
intz;
}

Çdo klasë deklaron një fushë me një emër unik. Ne do ta konsiderojmë këtë fushë si një shembull të një grupi të vetive unike të natyrshme në një lloj objekti.
Objektet e klasës Parent kanë vetëm një fushë x, që do të thotë se vetëm referencat e tipit Parent mund t'u referohen objekteve të tilla. Objektet e klasës ChildY kanë një fushë y dhe një fushë x të trashëguar nga klasa Parent. Prandaj, referencat e tipit ChildY ose Parent mund të tregojnë objekte të tilla. Shembull:

Prindi p = newChildY();

Vini re se kjo referencë p mund të hyjë vetëm në fushën x të objektit të krijuar. Fusha y nuk është e disponueshme sepse përpiluesi, kur kontrollon korrektësinë e shprehjes p.y, nuk mund të parashikojë që referenca p do të tregojë një objekt të tipit ChildY në kohën e ekzekutimit. Ajo analizon vetëm llojin e vetë variablit dhe deklarohet si Parent, por kjo klasë nuk ka një fushë y, e cila do të shkaktojë një gabim përpilimi.
Në mënyrë të ngjashme, objektet e klasës ChildZ kanë një fushë z dhe një fushë x të trashëguar nga klasa Parent. Kjo do të thotë se referenca si ChildZ dhe Parent mund të tregojnë objekte të tilla.
Kështu, referencat e tipit Parent mund të tregojnë një objekt të cilitdo prej tre llojeve të konsideruara, ndërsa referencat e tipit ChildY dhe ChildZ mund të tregojnë vetëm objekte të të njëjtit lloj. Tani mund të kalojmë në konvertimin e llojeve të referencës bazuar në një pemë të tillë trashëgimie.
Zgjerim nënkupton kalimin nga një lloj më specifik në një lloj më pak specifik, d.m.th. kalimi nga fëmijët te prindërit. Ngjashëm me rastin e llojeve primitive, ky kalim bëhet nga vetë JVM kur është e nevojshme dhe është "i padukshëm" për zhvilluesin, domethënë nuk kërkon ndonjë konvertim të veçantë.

Prindi p1=newChildY();
Prindi p2=newChildZ();

Në të dyja rreshtat variablat e tipit Prindit i është caktuar një vlerë e një lloji tjetër, që do të thotë se ndodh një konvertim. Për shkak se është një zgjatim, bëhet automatikisht dhe gjithmonë ka sukses.
Duhet të theksohet se me një transformim të tillë, asgjë nuk i ndodh vetë objektit. Pavarësisht se, për shembull, fusha y e klasës ChildY nuk është më e disponueshme, kjo nuk do të thotë se ajo është zhdukur. Një ndryshim kaq i rëndësishëm në objekt nuk është i mundur. Ai rrjedh nga klasa ChildY dhe ruan të gjitha vetitë e tij. Vetëm lloji i lidhjes përmes së cilës aksesohet objekti ka ndryshuar.
Tranzicioni i kundërt, domethënë lëvizja poshtë pemës së trashëgimisë te trashëgimtarët, është një ngushtim. Për shembull, në këtë rast, kalimi nga një referencë e tipit Parent , e cila mund t'i referohet objekteve të tre klasave, në një referencë të tipit ChildY, e cila mund t'i referohet vetëm njërës nga tre klasat, është padyshim një ngushtim. Një tranzicion i tillë mund të mos jetë i mundur. Nëse një referencë e tipit Parent i referohet një objekti të tipit Parent ose ChildZ, atëherë kalimi në ChildY është i pamundur, pasi në të dyja rastet objekti nuk ka fushën y, e cila deklarohet në klasën ChildY. Prandaj, kur ngushtohet, zhvilluesi duhet të tregojë në mënyrë eksplicite se është e nevojshme të përpiqet të kryejë një transformim të tillë. JVM do të kontrollojë korrektësinë e tranzicionit në kohën e ekzekutimit. Nëse është e mundur, konvertimi do të kryhet. Nëse jo, do të ndodhë një gabim (zakonisht një ClassCastException).

Prindi p=fëmija i ri();
ChildYcy = (ChildY)p; //djathtas
Prindi p2=newChildZ();
ChildYcy2 = (ChildY)p2; //gabim

Për të kontrolluar nëse tranzicioni i dëshiruar është i mundur, mund të përdorni shembullin e operatorit:

Prindi p=fëmija i ri();
nëse (p shembulli i Fëmijës)(
ChildYcy = (ChildY)p;
}

Prindi p2=newChildZ();
nëse (p2 shembulli ChildY) (
ChildYcy = (ChildY)p2;
}

Prindi p3=prindi i ri();
nëse (p3 shembulli i Fëmijës)(
ChildYcy = (ChildY)p3;
}

ky shembull nuk do të ketë gabime. Transformimi i parë është i mundur dhe do të kryhet. Në rastin e dytë dhe të tretë, kushtet e deklaratave if nuk do të funksionojnë dhe, për rrjedhojë, nuk do të ketë tranzicion të pasaktë.
Konverto në varg
Çdo lloj mund të hidhet në një varg, d.m.th. për shembull klasë String. Një konvertim i tillë është i jashtëzakonshëm për faktin se mbulon absolutisht të gjitha llojet.
Llojet e ndryshme konvertohen në një varg si më poshtë:

  • Llojet numerike shkruhen në formë teksti pa humbje të saktësisë së përfaqësimit. Së pari, bazuar në vlerën primitive, krijohet një shembull i klasës përkatëse "wrapper", më pas thirret metoda toString(). Por meqenëse këto veprime janë të padukshme nga jashtë, JVM i optimizon ato dhe i konverton drejtpërdrejt vlerat primitive në tekst.

  • Vlerat Boolean janë hedhur në vargun "true" ose "false" në varësi të vlerës.

  • Për vlerat e objektit, thirret metoda toString(). Nëse metoda kthen null, atëherë rezultati do të jetë vargu "null".

  • Për një vlerë null, gjenerohet vargu "null".
Konvertime të Ndaluara
Jo të gjitha kalimet ndërmjet llojeve arbitrare lejohen. Për shembull, konvertimet e ndaluara përfshijnë: kalimet nga çdo lloj referimi në primitiv dhe anasjelltas (përveç konvertimit në një varg), boolean mund të hidhet vetëm në këtë lloj ose në një varg. Për më tepër, është e pamundur të sillni me njëra-tjetrën klasa të vendosura në degët fqinje të pemës së trashëgimisë. Në shembullin, i cili u konsiderua se ilustron llojet e referencës, kalimi nga ChildY në ChildZ është i ndaluar.
Kjo listë e transformimeve të ndaluara nuk është ezauruar. Është mjaft i gjerë dhe në të njëjtën kohë të gjitha opsionet janë mjaft të dukshme, kështu që ato nuk do të konsiderohen në detaje. Ata që dëshirojnë mund të marrin informacion të plotë nga specifikimi.
Sigurisht, një përpjekje për të kryer një konvertim të ndaluar do të shkaktojë një gabim.

Duke përdorur gips
Situatat e konvertimit të tipit mund të grupohen si më poshtë:

  • Caktimi i vlerave për variablat (caktimi). Jo të gjitha tranzicionet lejohen nën një transformim të tillë - kufizimet janë zgjedhur në atë mënyrë që të mos mund të ndodhë një përjashtim.

  • Thirrja e metodës. Ky konvertim zbatohet për argumentet e metodës ose konstruktorit të thirrur. Një cast i tillë nuk gjeneron kurrë gabime. Hedhja kryhet gjithashtu kur kthehet vlera e metodës.

  • Kast eksplicit. Në këtë rast, specifikohet në mënyrë eksplicite se për cilin lloj dëshironi të hidhni vlerën origjinale.

  • Operatori i lidhjes konvertohet në një varg argumentesh të tij.

  • Zgjerimi numerik. Operacionet numerike mund të kërkojë një ndryshim në llojin e argumenteve. Ky konvertim ka një emër të veçantë - të zgjeruar, pasi zgjedhja e llojit të synuar mund të varet jo vetëm nga vlera fillestare, por edhe nga argumenti i dytë i operacionit.
Detyra numër 8
Shtoni në projekt përdorimin e një cast për hierarkinë tuaj të klasës.

Folësi i mëparshëm ka përshkruar konvertim poshtë, por rritja (për mendimin tim) kërkon shpjegim shtesë, pasi pyetja është shumë popullore dhe interesante.

Si funksionon derdhja e tipit eksplicit

Shembulli juaj tregon konvertimin ( Upcasting):

List coll = new ArrayList();

Përkthehet në Rusisht si më poshtë: krijoni një sorrë, si një zog. Krijoni një grup dinamik, shkruani fletë. Në shumicën e situatave, përditësimi është krejtësisht i panevojshëm.
Megjithatë, tipi casting funksionon në intervistat e punës kur ju bëhen pyetje për trashëgiminë. Për shembull, faqja quizful.net në përgjithësi përmban shumë pyetje mbi casting-un e tipit. Prandaj, unë do të shpjegoj veçoritë që njoh.

Pra, në shembullin e mësipërm, ne kemi krijuar një objekt të tipit ArrayList, dhe një referencë të llojit List. Mos harroni aksiomat për këtë metodë:

1. Ju mund të lidheni me çdo prind. Edhe një shumë e vjetër. Kjo do të thotë, ju mund të hedhni referencën coll edhe në llojin Object. Përpiluesi do të kapërcejë çdo referencë klase të prindit, ose prind-prind, ose prind-prind...prind

2. Qasja në fushë - gjithmonë kthen fushën e referencës, jo fushën e objektit. Nëse nuk ka një fushë të tillë në klasën e referencës, do të ketë një gabim përpilimi.

Klasa A ( int x = 2; //Fusha mëmë ) Klasa B shtrihet A ( int x = 3; //Fusha që duhet të mbivendoset me int-in prind y = 5; //Fusha që nuk është në klasën mëmë. ) Testi i klasës ( kryesore e zbrazët statike publike (args me varg) ( A ab = new B(); //Up-conversion System.out.println("Int x = " + ab.x); ) )

Kthimi Int x = 2 . Nëse përpiqeni të hyni në një fushë të një objekti:

System.out.println("Int y = " + ab.y); //Gabim përpilimi

Përpiluesi juaj do të thotë se e keni gabim, pasi nuk e sheh një fushë të tillë me referencë (A ab). Të gjitha sa më sipër zbatohen akoma edhe nëse fushat tuaja janë të shënuara me modifikues statikë.

3. Thirrja e një metode jostatike: në këtë rast, do të kthejë metodën e objektit. Por kur hyn në një metodë statike, ajo kthen metodën e lidhjes.

Klasa D( boshllëk publik doSome()( //Metodë jostatike System.out.println("DoSome jostatike nga D"); ) boshllëk publik statik Action()( //Metodë statike System.out.println("Veprim statik nga D "); ) ) klasa publike Okey zgjeron D( public void doSome()( System.out.println("doSome from Okey"); ) public static void Action()( System.out.println("Veprim statik nga Okey" );

DoSome jostatike nga Okey

Veprim statik nga D

Përgjigja është e thjeshtë, një metodë jostatike është një metodë objekti, një metodë statike është një metodë e klasës. Kur e quajmë një metodë jostatike, përpiluesi e kupton këtë: fluturo si sorrë. Kur ne e quajmë statike - fjalë për fjalë, fluturoni si zog.

4. Nëse ka një thirrje për një metodë që përshkruhet në klasën e objektit, por nuk përshkruhet në klasën e referencës, do të ndodhë një gabim përpilimi. Sepse metoda thirret me referencë:

Klasa A () Klasa B zgjeron A ( void someMethod()(); boshllëk publik statik kryesor (String args) ( A ab = new B(); ab.someMethod(); //Gabim përpilimi. ) )

5. Një konstruktor objekti (kur krijohet me komandën e re) funksionon në të njëjtën mënyrë sikur t'i jepni një referencë klasës suaj.

Artikulli i dhënë:

  • shkruar nga ekipi. Shpresojmë se do të jetë e dobishme për ju. Gëzuar lexim!
  • ky është një nga artikujt tonë

Konvertimi i tipit është një temë që mund të duket e frikshme për programuesit fillestarë Java. Sidoqoftë, ne ju sigurojmë, në fakt, gjithçka është e thjeshtë. Gjëja kryesore për të kuptuar sipas çfarë ligjesh ndodh ndërveprimi ndërmjet variablave dhe mbani mend këtë kur shkruani programe. Pra, le ta kuptojmë.

Në Java, ekzistojnë 2 lloje transformimesh - një fotografi për t'ju ndihmuar:

Kujtojmë se i gjithë "Java Universe" përbëhet nga:

  • Llojet primitive (byte, short, int, long, char, float, double, boolean)
  • objektet

Në këtë artikull ne:

  • merrni parasysh konvertimin e tipit për llojet primitive të variablave
  • transformimi i objekteve (String, Scanner, etj.) nuk merret parasysh në këtë artikull, pasi një "magji" e veçantë ndodh me objektet - kjo është një temë për një artikull të veçantë.
Konvertimi automatik

Epo, mirë, le të përpiqemi të kuptojmë se çfarë është "konvertimi automatik".

Mos harroni kur shikuam llojet e variablave (në artikull) e thamë atë një variabël është një lloj "enë" Një që mund të ruajë një vlerë për përdorim të mëvonshëm në program. Ne folëm gjithashtu për faktin se çdo lloj ndryshore ka gamën e vet të vlerave të vlefshme dhe sasinë e memories që zë. Këtu është shenja ku shkruhej:

Pra, kjo është ajo që ne po arrijmë në të vërtetë. Për më tepër, nuk ishte aspak e lehtë për ju që t'ju jepeshin vargjet e vlerave të vlefshme dhe sasia e memories së zënë 🙂

Le të krahasojmë, për shembull:

1. bajt dhe i shkurtër. byte ka një gamë më të vogël vlerash të vlefshme se sa të shkurtër. Kjo do të thotë, byte është si një kuti më e vogël, dhe shorti është një kuti më e madhe. Dhe kjo do të thotë shkurtimisht mund të vendosim bajt.

2. bajt dhe ndër. byte ka një gamë më të vogël vlerash të vlefshme se int. Kjo do të thotë, byte është si një kuti më e vogël, dhe int është një kuti më e madhe. Dhe kjo do të thotë ne mund të vendosim bajt në int.

3.int dhe të gjatë. int ka një gamë më të vogël vlerash të vlefshme se sa të gjata. Kjo do të thotë, int është si një kuti më e vogël, dhe e gjata është një kuti më e madhe. Dhe kjo do të thotë ne mund të fole int gjatë.

Ky është një shembull i konvertimit automatik. Kjo mund të përshkruhet në mënyrë skematike në formën e figurës së mëposhtme:

Le të shohim se si funksionon kjo në praktikë.

Shembulli #1

Kodi #1 - nëse e përdorni këtë kod në kompjuterin tuaj,

Testi i klasës ( kryesore e zbrazët statike publike (args me varg) ( bajt a = 15; bajt b = a; System.out.println (b); ) )

Testi i klasës (

byte a = 15 ;

bajt b = a ;

Kodi #2 - nëse e përdorni këtë kod në kompjuterin tuaj, tastiera do të shfaqë numrin 15

Testi i klasës ( kryesore e zbrazët statike publike (args me vargje) ( bajt a = 15; int b = a; System.out.println (b); ) )

Testi i klasës (

kryesore e zbrazët statike publike (args me vargje)(

byte a = 15 ;

int b = a ;

Sistemi. jashtë . println(b);

Dhe-dhe-dhe? A mendoni se sa herë u printua i njëjti numër në tastierë, dhe kodi #1 ndryshon nga kodi #2 vetëm në llojin e ndryshores b atëherë nuk ka dallim mes tyre? E nuk është kështu.

Kodi #2 përmban automatikekonvertimi i tipit , por në kodin nr. 1 - nr:

Edhe pse numri është në thelb i njëjtë, por tani është në b rreth një enë më e madhe që zë më shumë hapësirë ​​në disk. Duke vepruar kështu, JVM ekzekuton konvertimet automatike për ty. Ajo e di atë ndër me shume se bajt .

Cast

Një tjetër gjë është nëse po përpiqeni të transferoni diçka nga një enë më e madhe në një më të vogël.

Ju mund ta dini se një enë më e madhe përmban diçka që përshtatet në një të vogël - por JVM nuk e di këtë dhe përpiqet t'ju mbrojë nga gabimet.

Prandaj, duhet të "thoni drejtpërdrejt" se situata është nën kontroll:

Testi i klasës ( kryesore e zbrazët statike publike (args me vargje) ( int a=0; e gjatë b=15; a = (int) b; ) )

Testi i klasës (

kryesore e zbrazët statike publike (args me vargje)(

int a = 0;

e gjatë b = 15;

a = (int ) b ;

Këtu kemi shtuar (int) para b. Nëse ndryshorja a ishte, për shembull, bajt, në kllapa do të ishte (byte) . Formula e përgjithshme duket kështu:

Ajo thotë "bëni vlerë (më të madhe). b një variabël i llojit (objektiv) që më nevojitet ndër ".

Nëse diçka shkoi keq.

Deri më tani, ne kemi parë situata duke supozuar se e dimë saktësisht se çfarë po bëjmë. Por, çka nëse përpiqeni të vendosni në një enë diçka që nuk përshtatet atje?

Rezulton se vetëm ajo që "përshtatet" do të mbetet në enë. Për shembull, pjesa e pjesshme e numrave me pikë lundruese do të "ndërpritet":

//shembulli 1 Test i klasës ( publik static void main(String args) ( double a=11.2345; int b=(int)a; System.out.println(b); // tastiera do të shfaqë numrin 11 ) )

//shembulli 1

Testi i klasës (

kryesore e zbrazët statike publike (args me vargje)(

dyfishi a = 11,2345;

int b = (int ) a ;

Sistemi. jashtë . println(b); // tastiera do të shfaqë numrin 11

Duhet mbajtur mend se pjesa e pjesshme jo të rrumbullakosura, por i hedhur poshtë.

Por çfarë ndodh nëse përpiqemi të vendosim një numër që është jashtë kufijve? Për shembull, nëse në bajt (vargu i bajtit nga -128 në 127) vendosni numrin 128? Mendoni se do të marrim 1? Nr. Ne marrim -128:

Testi i klasës (produkti publik statik i zbrazët (args me vargje) (dyfishtë a=128; bajt b=(bajt)a; System.out.println(b); //do të shohim -128 në tastierë) )

Vlera e një ndryshoreje mund të llogaritet nga një konvertim i tillë, por qëllimi i programuesit është të parandalojë një situatë ku vlera është jashtë kufijve, pasi kjo mund të çojë në punë e gabuar programet.

Detyrat:
  1. Shkruani në mënyrë sekuenciale në përpilues konvertimet e të gjitha llojeve primitive me njëri-tjetrin, duke përfshirë llojet e shkronjave dhe Bëni një tabelë si kjo:
bajt shkurt karakter ndër gjatë noton dyfishtë logjike
bajt
shkurt
karakter
ndër
E gjatë
noton
dyfishtë
logjike

Në kryqëzim, shkruani: a - nëse konvertimi ndodh automatikisht, në - nëse keni nevojë të përdorni një konvertim të qartë, x - nëse konvertimi nuk është i mundur.

* hedhja e një tipi në vetvete quhet identike- nuk është e nevojshme të shkruhet

  1. Shikoni përsëri se çfarë madhësie ka çdo lloj primitiv. Përpiquni të bëni një diagram bllok që tregon se ku shkojnë llojet. Rrëshqitni shigjetat e etiketuara "transformimi i zgjeruar" dhe "transformimi ngushtues".
Pyetje

Kur intervistoni për një pozicion Zhvilluesi Junior Java, mund t'ju kërkohet:

Çfarë dini për konvertimin e llojeve primitive të të dhënave, a ka ndonjë humbje të të dhënave, a është e mundur të konvertohet një lloj boolean?

Mundohuni t'i përgjigjeni pyetjes.

Për të përmbledhur:
  • Nëse "vendosni" përmbajtjen e një ene më të vogël në një enë më të madhe, konvertimi është automatik dhe nuk duhet të ketë gabime.
  • Nëse është e nevojshme të vendosni "një vlerë nga një enë më e madhe në një më të vogël", duhet të jeni të kujdesshëm dhe të përdorni derdhje të tipit eksplicit.
  • Kur hedhni tipe float ose dyshe në integrale, pjesa e pjesshme nuk rrumbullakoset, por thjesht hidhet.
  • Lloji boolean nuk është hedhur në asnjë nga llojet.
  • Lloji char është hedhur në lloje numerike, si një kod karakteri në sistemin UNICODE.
  • Nëse numri është më i madh se kontejneri i tij, rezultati do të jetë i paparashikueshëm.

Ky artikull përshkruan vetëm një pjesë të materialit mbi temën e derdhjes së tipit. Ekzistojnë gjithashtu hedhje të llojit të objektit, hedhje string (në fund të fundit, çdo gjë mund të shkruhet në një varg, apo jo?), dhe promovim automatik i tipit në shprehje.

Shpresojmë që artikulli ynë të ishte i dobishëm për ju. Është gjithashtu e mundur të regjistroheni në kurset tona Java në Kiev. Ne stërvitemi nga e para. Informacion i detajuar Mund të na gjeni në.


Artikujt kryesorë të lidhur