Namo

4. Sintaksė ir semantika

Kadangi Java remiasi daugiausia C/C++ kalbomis, tie kurie moka šias kalbas ras šiame skyriuje daug pažįstamų dalykų. Java kūrėjai turėjo paprastą tikslą: jie norėjo panaudoti gerąsias C/C++ savybes perkeliant ją į Interneto ir Intraneto panaudojimo sritis. Kartu Java turėjo išspręsti silpnąsias C/C++ savybes, t.y. saugumo, perkeliamumo ir palaikomumo problemas. Jie taip pat pridėjo daugelio gijų palaikymą ir išimčių (exception ) apdorojimą, kad būtų lengviau programuoti Internetui. Todėl, skirtumai tarp C/C++ ir Java daugiausiai atsispindi paminėtose kategorijose.

Dauguma šio skyriaus informacijos buvo aprašyta pagal Java kalbos specifikaciją 1.0. Java vis dar keičiasi, dabar vis plačiau naudojama Java 2, ateityje reikia tikėtis naujų pasikeitimų. Kalbos konstruktoriai vis dar įtraukia kai kuriuos anksčiau nenaudotus raktinius žodžius ir pasiūlo naujų.

Šitas skyrius galės tarnauti kaip nuoroda, kur jūs galėsite grįžti vėl ir vėl iškilus programavimo problemom. Todėl rekomenduoju visiems bent trumpai susipažinti su šiuo skyriumi. Ypač, net patyrusiems programuotojams, reikėtų atkreipti dėmesį į masyvai ir išimtys (exceptions ) skyrelius. Java apdoroja masyvus ir išimtis (exceptions ) skirtingai, nei jūs galite tikėtis remiantis kitų programavimo kalbų žiniomis.

Šiame skyriuje mes aptarsime tokius Java sintaksės elementus:

Identifikatoriai ir unikodas

  Vardas (identifikatorius)  yra techninis terminas naudojamas pavadinti mūsų programos elementus. Viskas ką mes sukuriame mūsų Java programoje, t.y. kintamieji, metodai ir klasės, yra pavadinami vardais. Identifikatorius yra sudarytas iš unikodo simbolių sekos. "Kodėl unikodo? Niekada negirdėjau apie tokį." - galite sau pasakyti.

Java buvo padaryta kad būti lengvai perkeliama ne tik per kompiuterių platformas bet taip pat ir per nacionalinius barjerus. Daugiakalbiškumo palaikymas tapo aktuali tema kompanijoms, kurios varžėsi dėl savo produktų panaudojimas globaliose rinkose. Anksčiau dauguma kompiuterinių programų buvo rašomos anglų kalba. Ne anglakalbiai šalių programuotojai buvo priversti programuoti užsienio kalba. Kompiuteriai pritraukė aibę programuotojų su poreikiu prakalbinti programas savo šalių kalba. Čia unikodas ir ateina į pagalbą.

Unikodas buvo sukurtas unikodo konsorciumo ir buvo pirmą kartą viešai paskelbtas 1990. Jis padarytas užkoduoti daugumą modernių ir istorinių kalbų. Kiekvienam simboliui išsaugoti buvo paskirta 16 bitų. Dauguma vartotojų yra tikriausiai pažįstami su ASCII simbolių seka, kuri naudoja 7 bitus kad apibrėžti kiekvieną simbolį. Unikodas naudoja ekstra bitus, kad pridėti daugeliui kalbų būdingus simbolius ir suteikti diakritinius (atskirtinius) ženklus. Diakritiniai ženklai naudojami parodyti kaip žodis yra kirčiuotas. Daugelis ne anglų kalbų naudoja diakritinius simbolius. Lietuvių kalba turi taip pat 9 (ą,č,ę,ė,į,š,ų,ū,ž) simbolius, kurių nėra Lotynų abėcėlėje. Lietuviško teksto spausdinimo problemą mes jau gvildenome antrame skyriuje Lietuviško teksto spausdinimas skyrelyje.

Java programos yra rašomos unikodu ir visos eilutės ir simboliai yra išsaugojami kaip 16 bitų unikodo simboliai. Ar jums reikia išmokti naujas simbolių eilės reikšmes? Laimei, tai visai nebūtina. Unikodas tiesiog praplečia jūsų programavimo galimybes. Jeigu jūs anksčiau programas rašėte anglų kalba, galite tęsti tai ir toliau. Java kompiliatorius konvertuos kiekvieną ASCII failą į ekvivalentų unikodinį failą ir todėl visai nebūtina, kad Javos programos tekstas iš karto būtų rašomas naudojant unikodo simbolius.

Sun sprendimas panaudoti unikodą turi tam tikrų pasekmių. Java sukompiliuotas kodas užims maždaug dvigubai daugiau vietos. Tačiau tai nėra esminis trūkumas, nes Java nesivaržo dėl programos kompaktiškumo ir vykdymo greičio rekordų. Java pagrindinė paskirtis padaryti savo programas lengvai perkeliamas Internetu ir nepriklausomas nuo vartotojų kompiuterių platformų. Šie tikslai nesuderinami su atminties taupymu ir labai greitu skaičiavimu ir suteikiami unikodo privalumai yra neginčytini. Jei pradėsite pateikinėti savo Java programinius produktus tarptautinei rinkai, dar kartą įsitikinsite unikodo nauda.

Jeigu norite daugiau informacijos apie unikodą, paspauskite http://unicode.org nuorodą. Čia jūs rasite informaciją apie unikodo standartus, kaip gauti kietą standarto kopiją ir galėsite tapti šios organizacijos nariu.

Komentarai

Java palaiko C stiliaus komentarus ir prideda naują stilių, kad būtų galima automatiškai sukurti operatyvią dokumentaciją. Nesvarbu kurį komentarų stilių jūs naudojate; jie bus visi interpretuojami vienodai. Esmė ta, kad kompiliatorius nenaudos komentarų teksto formuojant vykdomosios programos komandas.

Visi C stiliaus komentarai yra tokie:

Java turi ir trečią komentavimo stilių, kuris naudojamas automatiškai dokumentuoti programą. Šiuos komentarus naudoja javadoc programa, kuri įtraukta į JDK rinkinį ir sukuria Interneto puslapį aprašantį jūsų kodą. Šio stiliaus komentarai yra įtraukiami į sukuriamą dokumentacijos Interneto puslapį. Komentarai naudojami automatinės dokumentacijos turi tokį formatą:

  

/** tekstas */

Kiekvienos kalbos kūrėjai susiduria su problema pagal kokias taisykles komentarai įterpinėjami vieni į kitus. Skirtingos kalbos apdoroja komentarus įvairiai ir Java šia prasme nėra išimtis. Taisyklės dirbant su Java komentarais yra tokios:

Pateiktas pavyzdys padės paaiškinti visų taisyklių prasmę. Kompiliatorius visą pavyzdžio eilutę interpretuos kaip vieną /* .. */ tipo komentarą:

 
 

/* normalūs komentarai su // /* /** simboliais viduje. Komentarai pasibaigia čia */

Raktiniai žodžiai

Kiekviena kalba turi grupę žodžių rezervuotą kompiliatoriaus panaudojimui. Šie  raktiniai žodžiai  negali būti naudojami kaip identifikatoriai jūsų programos. 4-1 lentelėje išvardinti raktiniai žodžiai rezervuoti Java kompiliatoriui. Pažymėti su žvaigždute žodžiai yra rezervuoti ateičiai. Kai kurie, tokie kaip konstanta, yra rezervuoti, kad programos kodo ir komentarų skaitymas neklaidintų programuotojo. Juos Java kalbos kūrėjai ateityje gali irgi įprasminti.

Java kalbos raktiniai žodžiai
abstractdoimplementspackagethrow
booleandoubleimportprivatethrows
breakelse*innerprotectedtransient
byteextendsinstanceofpublictry
casefinalint*rest*var
*castfinallyinterfacereturnvoid
catchfloatlongshortvolatile
charfornativestaticwhile
class*futurenewsuper** strictfp
*const*genericnull***switch
continue*gotooperatorsynchronized
defaultif*outerthis
4-1 lentelė. Vienetai pažymėti su žvaigždute - *, yra rezervuoti ateičiai, ** - buvo pridėti Java 2, *** - tiksliai kalbant null yra specialus kintamasis ir Java 2 versijoje nevadinamas raktiniu.
Aišku, čia pateikta lentelė galioja šiuo metu (Java 2, JDK 1.4) ir ateityje gali pasikeisti.

Duomenų tipai

Kintamasis gali būti vieno iš keturių rūšių duomenų tipo: klasės, interfeiso, masyvo ir pirminio tipo. Kompiliavimo metu kompiliatorius klasifikuoja kiekvieną kintamąjį kaip arba nuorodą arba pirminį. Klasėms, interfeisams ir masyvams išsaugoti naudojamos nuorodos. Pirminiai tipai yra duomenų tipai į kurį įtraukiami sveikieji skaičiai, slankaus kablelio skaičiai, simboliai ir loginiai. Pirminiai duomenų tipai yra išsaugojami tiesiogiai; jų užimamas dydis atmintyje yra apibrėžtas ir niekada nesikeičia.

Pirminiai duomenų tipai

Pirminiai tipai yra pagrindiniai kiekvienoje programavimo kalboje. Apie juos kompiliatorius žino iš anksto; kiekvienas vartotojo apibrėžtas tipas gali būti išskaidytas į pirminius tipus. Jie yra darbiniai blokai kurie yra naudojami net paprasčiausioje programoje. Su kiekvienu pirminiu tipu susipažinsime plačiau, kad vėliau galėtume juos naudoti savo Java programose.

Java kūrėjai iš anksto apibrėžė kiekvieno pirminio duomenų tipo dydį. Kiekvieno pirminio tipo užimama atmintyje vieta nepriklauso nuo mašinos ir todėl, skirtingai nuo C ir C++, Javos atveju pirminiam dydžiui nereikalinga size funkcija. Tai yra viena iš priežasčių, kodėl Java kodai yra pilnai perkeliami į skirtingų platformų kompiuterius.

Sveikieji skaičiai

Sveikasis skaičius žymi visus netrupmeninius skaičius. Mažiausias sveikojo skaičiaus pokytis yra lygus 1 arba -1. Dauguma skaičiavimų atliekami naudojant sveikuosius skaičius. Sveikojo skaičiaus skirtingus tipus galima atskirti pagal jų užimamą ilgį. Jų ilgis kinta nuo 8 iki 64 bitų. Javoje nėra sveikųjų skaičių tipo, kuris būtų be ženklo (unsigned). tipai jūs ne įprastai naudoja. 4-2 lentelėje pateikiamos kiekvieno sveikojo skaičiaus tipo charakteristikos.

Vardas Dydis
(bitų)
Minimumas Maksimumas Pavyzdys
byte   8 -128 127 16,-16
short   16 -32768 32767 99, -99
int   32 -2147483648 2147483648
99999, -99999
long   64 -922372036854775808 922372036854775807 100000000000
4-2 lentelė. Sveikųjų skaičių tipai.

Sveikojo skaičiaus simboliai gali būti išreikšti programoje vienu iš trijų pagrindu: jūs gali įvest jį pagrindu 10 (dešimtainiu), pagrindu 16 (šešioliktainiu) arba pagrindu 8 (aštuntainiu). Visi skaičiai yra laikomi dešimtainiais jei nenurodyta kokiu pagrindu jie užrašyti. Visi tiesiogiai užrašyti programoje skaičiai yra paverčiami tipu int  . Jūs galite pakeisti int   tipą su cast arba pabaigti skaičių raide  L , kuri nurodo kompiliatoriui, kad šis skaičius yra "long" tipo.

Šešioliktainis skaitmuo gali kisti diapazone nuo 0 iki 15. Raidės nuo  A  iki  F  išreiškia skaitmenis nuo 10 iki 15. Šešioliktainiai skaičiai naudingi tuo atveju, kai jums reikalingas skaičiaus dvejetainis kodas. Šia forma užrašyti dideli skaičiai užima mažiau

Pavyzdžiui užrašykime skaičių 32767 šešioliktaine forma. Jis yra didžiausia galima short   reikšmė. Jo šešioliktainis užrašas yra ox7FFF. Taigi, kiekvienas šešioliktainis skaičius pradedamas ox; čia didžiosios/mažosios raidės nesvarbu.

Aštuntainio skaičiaus požymis yra vedantysis nulis. To paties dešimtainio 32767 aštuntainis užrašas būtų toks: 077777 . Vedantysis nulis pasako kompiliatoriui, kad toliau užrašytas skaičius yra išreikštas aštuntainia forma.

Sveikieji skaičiai pasižymi taip vadinamas cikliško perkėlimo savybe. Jeigu jūs mėginsite vienetu arba padidinti arba sumažinti sveikąjį skaičių, kuriam išreikšti neužtenka tam tipui skirtos atminties, skaičiaus reikšmė bus pakeista cikliškai. Paimkime byte   tipo skaičių, kurio reikšmė yra 127. Jeigu jūs padidinsite vienetu šitą skaičių, jo reikšmė taps lygi -128. Tai yra skaičius tampa iš didžiausio teigiamo mažiausiu neigiamu byte tipo skaičiumi. Atvirkščiai, jei būtų iš byte tipo skaičiaus lygaus -128 atimtas 1, jis virstų 127. Pasirenkant sveikojo skaičiaus tipą, turite įvertinti koks bus jo kitimo diapazonas ir pagal tai išsirinkti konkretų tipą.

Slankaus kablelio skaičiai

Java realizuoja viengubo ir dvigubo tikslumas slankaus kablelio skaičius, kuriems teisinga nurodyta IEEE standarte binarinių slankaus kablelio skaičių aritmetika. Šios dvi formos yra atitinkamai: float   ir double tipo. float   yra 32 bitų viengubo tikslumo slankaus kablelio skaičius. double tipas yra 64 bitų ilgio ir naudojamas aprašyti skaičius dvigubu tikslumu.

Slankaus kablelio skaičiai gali saugoti specialiai apibrėžtas reikšmes: neigiama begalybė, neigiamas nulis, teigiamas nulis, teigiama begalybė ir ne skaičius (NaN). Kadangi šios reikšmės yra apibrėžtos Java kalboje, jūs galite jas naudoti savo kode. Kai atsitinka speciali situacija - nulis padalintas iš nulio, rezultatas bus gautas kaip NaN. Tai yra naudinga programuojant, nes bet kuriuo atveju galima atlikti dalybos veiksmą.

Visi tiesiogiai parašyti slankaus kablelio laikomi double tipo, jei jų tipas nenurodytas. Kad skaičius būtų 32 bitų float  , jį reikia parašyti su f raide pabaigoje. Taip kompiliatoriui yra pasakoma, kad šitas skaičiusbūtų išsaugotas kaip float . Kadangi Java tikrina tipus priskyrimo metu, jūs bus turite suprasti kokio tipo skaičių priskiriate slankaus kablelio kintamiesiems.

Pateikto kodo fragmentas generuos kompiliatoriaus klaidą, nes priekirimo metu bus aptikta, kad tipai nesiderina:

  

float Num = 1.0;

Kadangi visi tiesiogiai užrašyti slankaus kablelio skaičiai yra laikomi double   tipo skaičias, jums reiks apibrėžti kad 1.0 yra float   parašant f po 1.0, t.y. 1.0f. Pataisytas kodas atrodytų taip :

  

float Num = 1.0f;

Atkreipkite dėmesį, kad slankaus kablelio skaičius naudoti programos vykdymo valdymui kontroliuoti yra rizikinga. Du slankaus kablelio skaičiai gali būti praginos metu palaikyti lygiais, jei daug jų dešimtainių ženklų sutampa, nors matematine prasme jūs užrašėte skirtingus skaičius. Naudojant slankaus kablelio skaičius ciklo skaitliuko kintamajam ciklo operatorius lėčiau vykdomas ir gali atsirasti sunkiai prognozuojamų praginos rezultatų. Pvz. sunku iš prognozuoti ar 0.333333333333333 sutaps su 0.3333333333333333 ar ne.

Simboliai (characters )

Simboliams saugoti naudojamas unikodo standartas (žr. šito skyriaus dalį "Identifikatoriai ir unikodas" ). Kiekvienas simbolis išsaugojamas 16 bitų numeriu. Unikodas leidžia jums saugoti daugelį skirtingų neatspausdinamų arba užsienio kalbos simbolių. Kad apibrėžti simbolį tiesiogiai, jūs galite naudoti arba normalius simbolius arba unikodo perėjimo (escape) sekas. Bet kuriu atveju, jums reikės patalpinti reikšmę tarp poros viengubų kabučių.

Unikodas perėjimo (escape) seka gali būti nurodyta naudojant du metodus. Pirmaa būdas bus pažįstamas C/C++ programuotojams. 4-3 lentelėje iliustruojamos Jūs galite perėjimo (escape) į unikodą sekos.

Perėjimo
(escape)
sekos
Paskirtis Unikodas
\b Tarpas \u0008
\t Horizontalus tarpas \u0009
\n Eilutės perdavimas \u000a
\f Eilutės perstūma \u000c
\r Karietėlė \u000d
\" Dviguba kabutė \u0022
\' Vienguba kabutė \u0027
\\ Pasviras brūkšnys \u005c
4-3 lentelė. Perėjimo (escape) į unikodą sekos.

Jūs taip pat galite pereiti į unikodo sekas surenkant \u pratęstas keturženkliais šešioliktainiais skaičiais, kurie nurodo specifinį jums reikalingą simbolį. Skaičius gali kisti diapazone nuo \u0000 iki \u00ff. Keletas unikodo simbolių pavyzdžių:

Loginiai kintamieji

Loginiai kintamieji gali turėti tik dvi reikšmes: true  arba false . Skirtingai nuo C, jūs negalite priskirti sveikuosius skaičius loginiams kintamiesiems. Kad generuoti atitinkamą loginę reikšmę, jūs galite palyginti sveikąjį skaičių su 0. Konvertuojant sveikąjė skaičių   i   į loginį, jūs galite naudoti tokias Java komandas:

  

int i; boolean b; b = (i != 0);

Čia mes yra panaudojome nelygus operatorių, kad patikrinti ar  i  lygus nuliui. Skliausteliai reikalingi, kad išraiška būtš skaičiuojama teisinga tvarka.

Loginiai kintamieji yra svarbi Java ir kitų kalbų koncepcija. Kai ir kitos kalbos, jie naudojami ciklams valdyti. Java ciklai jums bus lengvai suprantami, jei žinote jų sintaksę C kalboje.

Pirminių duomenų tipų konvertavimas

Konvertavimas tarp dviejų pirminių duomenų tipų yra bendra praktika. Sunkumas konvertuojant vieną kintamąjį į kitą yra tame, kad jūs turite suprasti savo sprendimo galimas pasekmes. Je esate neatidus, galite prarasti dalį informacijos ir gauti netikėtą rezultatą.

Java visuomet tikrina tipus. Kompiliatorius automatiškai nekonvertuoja vieno tipo į kitą. Jums reikia tiksliai nurodyti, kad norite pervesti vieno tipo kintamąjį į kitą. Šis mechanizmas vadinamas tipo pakeitipu (angl. cast). Jis pasako kompiliatoriui konvertuoti iš vieno tipo į kitą. Kitose kalbose yra liberasnės skirtingų tipų kintamųjų priskyrimo taisyklės. Java priverčia programuotoją keičiant tipą sąmoningai pasakyti: "Aš suprantu, kad naudodamas šį tipo pakeitimą galiu prarasti dalį informacijos, bet mano programos atveju tai neturėtų pakenkti".

Java tipų pakeitimas nurodomas analogiškai kaip ir C/C++ kalboje. Jūs užrašote norimą tipą skliausteliuse prieš keičiamą kintamąjį. Jeigu tipo konvertavimas palaikomas, rezultatas yra apskaičiuojamas ir atliekamas priskyrimas. Tarkime jūs turite du kintamuosius: shortVar ir intVar (shortVar tipo short   ; intVar tipo int). Šiuo atveju galimi du tipų konvertavimo variantai:

  

short shortVar=0; int intVar=0; intVar = shortVar; shortVar = intVar; // nesuderinami priskyrimo tipai. // Šioje vietoje bus pažymėta kompiliavimo klaida

Kompiliuojant šitą kodą gausime kompiliavimo klaidą, nes priskyrimas shortVar = intVar duos nesuderinamų tipų kintamųjų priskyrimo klaidą. Jūs mėginate priskirti didesnio kitimo diapazono kintamąjį (intVar, tipas int ) mažesnio kitimo diapazono (shortVar, tipas short ). Toks tipo konvertavimas vadinamas siaurinimo konvertavimu. Siaurinimo atveju jūs galite prarasti dalį informacijos. Tiesą sakant jūs ją prarandate visuomet; nors tuo atveju, kai visi prarandami bitai yra nuliniai, laikoma, kad siaurinimo nuostolių nebuvo. Pavyzdžiui, konvertuojant iš long   (64 bitai) į int   (32 bitai), jūs turite padaryti protingą sprendimą, kad būtų nenukenčiama dėl galimo informacijos praradimo. Jeigu jūs užtikrinti kad long   reikšmės neišeis iš int kitimo diapazono, galite naudoti tipo pakeitimą (cast); kitu atveju, jums vertėtų bent atspausdinti perspėjimą vartotojui, kad dalis informacijos priskyrimo metu galėjo dingo.

Perrašykime naujai anksčiau parašytą kodą:

  

short shortVar=0; int intVar=0; intVar = shortVar; shortVar = (short) intVar;

Kompiliatorius dabar leis jums padaryti paskutinį priskyrimą. Sveikasis skaičius intVar bus būti konvertuotas į short   praleidžiant aukštesniuosius bitus ir išsaugojant skaičius ženklo skiltį. case   operatorius pasako, kad norite iš 32 bitų sveikojo skaičiaus pereiti 16 bitų short   skaičių panaikinant vyriausiuosius 16 bitų.

4-4 lentelė 4-4 parodyti galimi pirminių tipų konvertavimai. C reiškia, kad jūs keičiant tipą turite naudoti (cast) operatorių; jei to napadarysite - gausite kompiliavimo klaidą. L pažymi, kad tipų konvertavimo metu yra galimas dalinis informacijos praradimas. X žymi, kad šios tipų poros konvertavimas Java kalboje neleidžiamas.

Pradinis
  tipas
Paskirties tipas
  byte   short   int   long   float   double char   boolean
  byte   C X
  short   C, L C X
  int   C, L C, L C, L X
  long   C, L C, L C, L C, L C C, L X
  float   C, L C, L C, L C, L C, L X
  double C, L C, L C, L C, L C, L C, L X
  char   C, L C C C C C C X
  boolean X X X X X X X
4-4 lentelė. Pirminių tipų konvertavimas.
C reiškia, kad konvertuoti jūs turite naudoti (cast) operatorių;
L žymi, kad konvertavimo metu prarandamas tikslumas;
X žymi atvejus, kai konvertavimas draudžiamas.

Slankaus kablelio į sveikąjį skaičių

Kada konvertuojama iš slankaus kablelio skaičiaus į kiekvieną sveikojo skaičiaus tipą, jūs visuomet prarandate visą trupmeninę informaciją. Java atmeta trupmeninę reikšmę apvalindama skaičių link nulio. Gautas sveikasis skaičius gali neteisingai atspindėti ir sveikąją dalį, jei konvertuojamasis slankaus kablelio skaičius buvo pakankamai didelis.

double tipo į float konvertavimas

Konvertavimas iš double tipo į float   bus atliekamas pagal IEEE 754 nustatytą standartą. Reikšmės kurios yra per didelės kad tilpti į float   diapazoną bus pakeistos NaN (ne skaičius) reikšme.

Loginis į arba iš bet kurio tipo

Konvertavimas į arba iš loginio kintamojo tipo į kitus pirminius tipus Java kalboje neleidžiamas. Jeigu jūs norite konvertuoti iš sveikojo skaičiaus į loginį arba loginį į tekstą, jūs turite rankiniu būdu konvertuoti šias reikšmes. Pavyzdžiui, galite naudoti tokį kodą:

  

boolean bool; int i=15; String st=null; if (i == 0) bool = false; else bool = true; if (bool) st = "true"; else st = "false";

Informaciją apie nuorodų duomenų tipų ( class, interface, array ) konvertavimą rasite šio skyriaus skyrelyje "Objektai".

Kintamųjų paskelbimas

Java kintamasis  gali būti pirminio tipo, objektas arba interfeisas. Kintamąjį galima paskelbti bet kurioje programos dalyje. Kiekviena paskelbimo komanda gali būti pratęsta pradinės reikšmės priskyrimo operatoriumi.

Iš anksčiau pateiktų pavyzdžių matyti, kad kintamieji paskelbiami ir jiems priskiriamos pradinės reikšmės gana paprastai. Pateiksime dar keletą pavyzdėlių:

  

int i=42; String it="Hello World"; float pi=3.14f; boolean cont;

Dar kartą pabrėšime, kad kintamasis gali būti paskelbtas bet kurioje programos vietoje; paskelbimo operatorių galite pratęsti pradinės reikšmės priskyrimu, bet tai nėra būtina.

Galiojimas

Kiekvienas paskelbtas kintamasis turi savo gyvavimo trukmę, arba kontekstą, kuris priklauso nuo to, kurioje vietoje kintamasis yra paskelbtas. Kada jūs Java programos kodo dalį apgaubiate riestiniais skliaustais {}, jūs apibrėžiate naują galiojimo lygį. Galiojimo lygis apibrėžia kada reikia kintamąjį atlaisvinti ir kur šis yra pasiekiamas. Kintamieji pasiekiami tik tuo atveju, jeigu jie buvo paskelbti einamojo konteksto bloke arba juos paskelbė vienas jų tėvų.

Kada išeinama iš galiojimo lygio, kiekvienas kintamasis, kuris buvo paskelbtas to lygio bloke tampa nepasiekiamas. Jeigu kintamasis buvo pirminio tipo, jis nustoja galioti iš karto. Kitaip yra su nuorodų tipų kintamaisiais. Nuorodos atveju šiukšlių surinkėjas nusprendžia kada kintamąjį iš tikrųjų galima atlaisvinti. Taip bus tik tada, kai daugiai nebus nuorodos į tą kintamąjį. Taigi, pirminių duomenų tipų kintamieji atlaisvinami visada, kai išeinama iš konteksto bloko. Analogišku atveju nuorodos kintamasis gali būti atlaisvintas arba ne, tai sprendžia šiukšlių surinkėjas.

Galiojimo taisykles lengviau suprasti jeigu programos blokus įsivaizduoti medžio šakomis. Kiekvienas naujas blokas sukuria naują medžio šaką. Kuo didesnis bloko lygis, tuo aukštesnėje medžio vietoje jis bus patalpintas. Pateiksime programos kodo pavyzdį ir jos blokų galiojimo medį:

  

class foo { int cnt; public void test1() { int num; } public void test2() { for(int cnt=0; cnt < 5; cnt++) { System.out.println(cnt); } } }

4-1 paveikslėlis iliustruoja šios klasės blokų galiojimo pirmumo medį.

4-1 paveikslėlis. Galiojimas medis.

Pastebėkime, kad kiekvienas naujas blokas sukuria naują galiojimo šaką. Medis prasideda nuo paketo (package ) lygio, kuriam priklauso visos klasės ir interfeisai. Kitą lygį sukuria klasės kintamieji ir klasės metodų vardai. Kiekvienas klasės metodas pradeda jų pačių galiojimo lygį; jų lokalūs kintamieji yra apibrėžti tik čia. Pastebėkime, kad daliniu atveju metodas test2 neturi lokalių kintamųjų paskelbtų pirmame kontekste, bet cikle sukuriamas naujas kontekstas ir jame yra apibrėžtas kintamasis vadinamas cnt. Šitas kintamasis užgožia anksčiau aukštesniame klasės lygyje paskelbtą cnt.

Ne C programuotojams for ciklas gali būti naujas. Plačiau apie ciklus kalbėsime "Programos praginos eigos valdymo" skyrelyje.

Turint daugelį galiojimo lygių atsiranda galimybė maskuoti arba užgožti kitus kintamuosius. Sakykime jūs sukūrėte klasės kintamąjį cnt. Po to klasės metode jūs taip pat sukūrėte kintamąjį cnt. Naujas kintamasis užgožtų arba paslėptų ankstesniojo klasės kintamojo cnt egzistavimą. Kiekvienas kreipimasis į cnt metodo viduje duotų naujojo cnt reikšmę. Kad pasinaudoti anksčiau apibrėžtu klasės kintamuoju cnt metodo viduje turėtume parašyti taip:

  

this.cnt = 4;

Yra bendra taisyklė vengti kintamųjų užgožimo. Tai suprantama, nes užgožiamų kintamųjų panaudojimas padaro programos kodą sunkiai skaitomu.

Kintamųjų pavadinimai

Kintamųjų vardai turi prasidėti raide. Jis gali būti be galo ilgas ir susidaryti iš raidžių, skaitmenų ir visų skyrybos simbolių išskyrus taško. Kintamieji negali kartoti kitų to paties galiojimo lygio identifikatorių. Tai reiškia, kad negali turėti kintamųjų su tuo pačiu vardu, kuris būtų:

Jeigu jūs naudojate unikodo simbolius (kad palaikyti ne anglų kalbą, pvz. lietuvių), tuomet jums reikia suprasti kaip Java atlieka simbolių palyginimą. Vardas (identifikatorius) bus lygus kitam, jeigu šis turi tiksliai tą pačių unikodo simbolių seką. Tai reiškia, kad lotynų didžioji A (\u0041) skirsis nuo graikų didžiosios A (\u0391). Taip pat reikia atsiminti, kad Java kalboje yra skiriamos didžiosios ir mažosios raidės.

Operacijos

Java palaiko daug operacijų. Operatoriaus simbolis naudojamas vykdant operacijas su vienu ir daugiau kintamųjų. Tipiniai operatorių pavyzdžiai yra plius (+), minus (-), lygu (=). Operatoriai yra klasifikuojami pagal naudojamų argumentų skaičių. Kai kurie operatoriai (pvz., kaip minus) turi skirtingas reikšmes priklausomai nuo to ar jis turi vieną ar du operandus.

. [] ()
++ -- ! ~ instanceof
* / %
+ -
<< >> >>>
< > <= >=
== !=
&
^
|
&&
||
?:
= Op=
,
4-5 lentelė. Operacijų eiliškumas. Eiliškumo tvarka yra iš viršaus į apačią. Tos pačios eilutės operacijos yra lygaus pirmumo.

Operatorius op= sutrumpintai žymi visas galimas operacijas su toliau einančiu = ženklu. Pavyzdžiui, +=, *=, |= ir taip toliau.

  Išraiška   yra operatorių ir operandų kombinacija. Išraiškos reikšmei apskaičiuoti naudojamos operacijų eiliškumo taisyklės. Operacija turinti eiliškumo pirmenybę prieš kitą bus vykdoma pirma. Tipinis pavyzdys galėtų būti dar mokykloje įsisavintas eiliškumo principas apskaičiuojant matematines išraiškas su atimties, sudėties ir daugybos bei dalybos operacijomis. Pavyzdžiui, x = 2+4*3 rezultatas bus x=14, bet ne 18.

Sudėtingų išraiškų atveju geriau tiesiog panaudoti skliaustelius, kad nesusipainioti su operacijų vykdymo tvarka. Taip apsaugosite ne tik save nuo klaidų, bet ir padidinsite savo programoms suprantamumą kitiems programuotojams. 4-5 lentelėje nurodytas operacijų eiliškumas. Operacijos kurios pasirodo toje pačioje eilutėje yra lygaus eiliškumo ir bus apskaičiuojamos iš kairės į dešinę.

Operacijos su skaičiais

Operacijos su skaičiais patenka į dvi kategorijos:  unarinės  operacijos, kurios dirba į vienu kintamuoju ir  binarinės  operacijos, dirbančios du dviem skaičiais. Toliau binarinius operatorius galime skirstyti į grąžinančius skaitinį rezultatą ir palyginimo operatorius, grąžinančius loginę reikšmę.

Operacijos rezultatas visuomet bus to paties tipo kaip didžiausio operando tipas. Tarkime sudedame du skaičius - vienas short  , kitas long   tipo. Sudėties rezultatas bus long  . 4-6 lentelėje aprašyti analogiški atvejai su kitais pirminiais tipais. Atkreipkite dėmesį, kad mažiausiais operacijų su sveikaisiais skaičiais grįžties rezultatas yra int. Pradžioje paanalizuosime unarines operacijas.

1 tipas 2 tipas Rezultatas
byte   byte   int  
byte   short   int  
byte   int   int  
byte   long   long  
short   short   int  
short   int   int  
short   long   long  
int   int   int  
int   long   long  
int   float   float  
int   double double
float   float   float  
float   double double
4-6 lentelė. : Operacijų rezultatai.

Unarinės operacijos

Unarinės operacijos reikalauja vieno operando - parametro. Operacija atliekama ir rezultatas patalpinamas operande. Rezultato tipas bus visuomet tas pats kaip ir pradinio tipo, nes čia nėra galimybės prarasti tikslumą arba dydį. 4-7 lentelėje išvardinti Java unariniai operatoriai.

Operacija Aprašymas
- Unarinis minus
+ Unarinis plius
~ Bitinis papildinys
++ Padidinimas vienetu
-- Sumažinimas vienetu
4-7 lentelė. Unariniai operatoriai.

Kai kurios galimos unarinės išraiškos:

Unarinis minus ir plius

  Unarinis minus   operatorius (-) naudojamas pakeisti skaičiaus ženklą. Neigiamas skaičius tampa teigiamu, o teigiamas skaičius tampa neigiamu. Unarinis plius operatorius iš tikrųjų neatlieka jokio darbo. Jis yra įvestas dėl simetriškumo.

Sveikojo skaičiaus ženklo pakeitimas gali būti interpretuojamas atėmimu iš nulio. Tai tiesa dėl visų bet ne didžiausio neigiamo skaičiaus; unarinis minus nekeičia šių skaičių. Priežastis yra ta, kad neigiamų skaičių yra vienu daugiau ir nėra kaip didžiausią neigiamą pakeisti teigiamu skaičiumi. Kad tai iliustruoti, pažiūrėkime kodo pavyzdį, kurio darbo rezultatas bus netikėtas: -128.

  

byte i=-128; System.out.println(-i);

Dirbant su slankaus kablelio skaičiai atsiranda keletas specialių atvejų. Skaičius su reikšmė NaN bus toks pat NaN ir po ženklo pakeitimo. Teigiamas ir neigiamas nuliai, kaip ir kitų skaičių atveju, pakeis ženklą. Tas pats teisinga ir teigiamai ir neigiamai begalybei.

Bitinis papildinys

  Bitinio papildinio  operacija atliekama su sveikojo skaičiaus tipo kintamaisiais. Jis sveikojo skaičiaus bitus su 1 pakeičia 0 ir atvirkščiai. Jei skaičius buvo x, tai ~x sutampa su (-x)-1. Kalbose, kuriose naudojami skaičiai be ženklo bitų papildymo operaciją duoda kitą rezultatą. Pavyzdžiui Paskalio byte atveju, 0 papildinys būtų 255; Javoje gausite, kad ~0 rezultatas yra -1.

Padidinimas vienetu ir sumažinimas vienetu

  Padidinimo vienetu   (++) ir   sumažinimo vienetu   (--) operatoriai yra sutrumpintas būdas pridėti 1 arba atimti 1. Jie gali būti parašyti arba prieš arba po kintamojo. Patalpinus ++ po operando, pirma apskaičiuojama išraiška ir po to operandas padidinamas vienetu. Patalpinus ++ prieš operandą, pirma operandas padidinamas vienetu ir po to apskaičiuojama išraiška. Pailiustruosime tai pavyzdžiu.

  

int i=0; int j=0; System.out.println(++i); System.out.println(j++);

Šios programos darbo rezultatas bus 1 ir 0. Pirma spausdinimo komanda pirma padidins   i   tuomet jį atspausdins. Kitu atveju kintamasis  j  bus atspausdintas ir tuomet padidintas vienetu. Pastebėkime kad abiem atvejais  i  ir  j   reikšmės pabaigoje bus lygios 1.

Binarinės operacijos

  Binariniai   operatoriai naudoja du operandus, atlieka veiksmą ir grąžina rezultatą. Rezultatas turi tą patį tipą kaip didžiausias operandas. Sudėdami byte   ir int   gausime rezultatą int   tipo. Operacijų rezultatas neįtakoja kintamųjų (operandų) reikšmes. Binarinės operacijos skaidomos į dvi grupes: pirmoji grąžina rezultate skaičiaus reikšmę, o antroji - loginę reikšmę. 4-8 lentelėje išvardintos binarinės operacijos, kurios grąžina skaičių.

Operacija Aprašymas
+ Sudėtis
- Atimtis
* Daugyba
/ Dalyba
% Modulis
& Bitinis AND
| Bitinis OR
^ Bitinis XOR
<< Su ženklu poslinkis į kairę
>> Su ženklu poslinkis į dešinę
>>> Be ženklo poslinkis į dešinę
Op= Kombinacija priskyrimas ir operacija
4-8 lentelė. Binarinės skaičiavimo operacijos.

Adityvios operacijos

  Adityvios   operacijos yra + ir -. Jeigu bent vienas operandas yra slankaus kablelio skaičius, jie bus abudu konvertuoti į slankaus kablelio skaičius. Kiekvieno tipo sveikasis skaičius išskyrus long  bus konvertuojamas į int  . Tai reiškia, kad adityvus operatorius niekada negrąžins byte   arba short   reikšmės. Kad priskirti rezultatą byte   arba short   tipo kintamajam, jūs turėsite panaudoti tipo pakeitimo (cast) operatorių. Atikdama slankaus kablelio skaičių sudėties ir atimties operacijas, Java laikosi IEEE taisyklių. Specialiais atvejais, pavyzdžiui sudedant du NaN slankaus kablelio skaičius, reikia pažiūrėti į kalbos specifikaciją, kad žinoti kaip tokie atvejai traktuojami.

Dauginimo operatoriai

  Dauginimo   operatoriai yra *, / ir %. Jie konvertuoja operandus panašiu būdu kaip ir adityvieji operatoriai. Operacijos su sveikaisiais skaičiais yra asociatyvios, išskyrus operacijas su slankaus kablelio skaičiais. Pavyzdžiui, įsivaizduokime mes turime du slankaus kablelio skaičius. Vienas yra teigiamas 1, kitas didžiausias išreiškiamas teigiamas skaičius:

  

float vienas = 1f; float max = 2^24e104;

Duotas kodas negrąžintų true :

  

vienas + max - vienas == max - vienas + vienas

Pirmu atveju mes pridedame 1 prie didžiausio išreiškiamo float  . Čia gausime perpildymą ir rezultatas bus teigiama begalybė. Atimant 1 iš begalybės gausime begalybę; taigi kairės pusės išraiškos rezultatas bus teigiama begalybė. Dešinės pusės išraiškoje atimamas 1 iš max , tuomet pridedamas 1 ir gauname reikšmę max .

Liekana (%) arba dalyba moduliu apibrėžiama taip, kad (a/b) * b + (a%b) = a. Šita operacija daro tai ko jūs tikitės, išskyrus tai, kad ji duoda teigiamą rezultatą, kai daliklis teigiamas ir neigiamą rezultatą kitu atveju. Rezultato absoliutinė reikšmė visuomet yra mažesnė už daliklį.

Pavyzdys su modulio operatoriumi:

  

int i=10; int j=4; int k=-4; System.out.println(i % j); // = 2 System.out.println(i % k); // = -2

Java dalybos liekanos operatorius skirtingai elgiasi nei nurodyta IEEE 754. Jeigu jūs norite panaudoti IEEE apibrėžimą, galite panaudoti matematinę biblioteką math.IEEEremainder.

Bitiniai operatoriai

Bitiniai   operatoriai yra naudojami, kai reikia atlikti operacijas su skaičiaus bitine išraiška. Jos turi prasmę tik dirbant su sveikaisiais skaičiais. Slankaus kablelio skaičių bitai sunkiai interpretuojami, todėl bitinis operacijos čia neturi aiškios prasmės. Bitiniai operatoriai ir (&) , arba (|) ir xor  (^) naudojami patikrinti individualius sveikojo skaičiaus bitus.

Tarkime mes naudojame kiekvieną byte  tipo skaičiaus bitą saugoti gairelę (flag  ). Mes galime saugoti aštuonias gaireles pažyminčias kiekvieną bitą. Pateiktas kodas parodo kaip galima atlikti manipuliacijas su bitais:

  

byte flags=0xff; // inicijuoja į 11111111 byte mask=0xfe; // trafaretas į 11111110 flags = flags & mask; // eilės 8 pozicija flags = flags | mask // išvalo 8 poziciją flags = flags ^ mask; // = 00000001

Postūmio operatoriai

Java palaiko tris   postūmius  : postūmį į kairę (<<), postūmį į dešinę (>>) ir be ženklo postūmį į dešinę (>>>). Visų postūmio operacijų išraiška yra postūmio operatorius ir jo dydis. Postūmio dydis turi būti sveikojo skaičiaus tipo. Jeigu jūs norite atlikti postūmį su slankaus kablelio skaičiumi, turite pakeisti jo tipą.

Postūmis su ženklu išsaugoja operando ženklą. Be ženklo dešinysis postūmis naudos pralėtimą nuliais. (  Pralėtimas nuliais   reiškia kad trūkstami bitai po perstūmimo bus užpildyti nuliais. Postūmis per 0 taip pat galimas, bet jis neturi prasmės.

Naudojant postūmio operaciją mes galime greitai atlikti sveikojo skaičiaus dalybą iš 2. Dešinysis postūmis išstums paskutinį bitą, o tai ekvivalentu dalinimui iš 2. Nelyginiai skaičiai po dalijimo iš 2 yra apvalinami iki mažesnės reikšmės:

  

int i = 129; // 10000001 dvejetainis i = i >> 1; // dabar 1000000 arba 64

Kombinacija priskyrimas

Išraiškos, kurios rezultatą priskiria pirmajam operandui, gali naudoti sutrumpintą žymėjimą. Reikia atkreipti dėmesį kaip veikia operandai su išraiškomis, kuriose yra ++ ir -- operacijos. Šiuo atveju jos veiks kitaip, nei įprasta. Pavyzdžiui

  

int i = 0; i += ++i;

rezultatas bus 1. Galima galvoti, kad turėtų gautis 2. Tačiau pirma  i   bus iškviestas į registrą, apskaičiuota ++i, priskirta atgal  i kintamajam ir naudojamas kaip kitas operandas + operatoriui. Toliau, kadangi pradinė  i reikšmė buvo 0, tai rezultate gausime 1.

Santykio operatoriai

Santykio operatoriai lygina dviejų skaitinių operandų reikšmes ir grąžina loginę palyginimo rezultato reikšmę. 4-9 lentelėje aprašyti galimi Javos palyginimo operatoriai.

Operatorius Aprašymas
< Mažiau kaip
> Didesnis kaip
<= Mažiau kaip arba lygus
>= Didesnis kaip arba lygus
== Yra lygūs
!= Nelygūs
4-9 lentelė. Santykio (palyginimo) operatoriai.

Naudojant santykio operatorius dažnai daroma tipinė klaida. Programuotojai naudoja viengubą lygybės ženklą vietoje teisingo dvigubo lygybės ženklo. Viengubas lygybės ženklas naudojamas priskirti reikšmę. Dvigubas lygybės ženklas naudojamas, kad palyginti du skaičius. Skirtingai nuo C/C++, Java pastebės tokias klaidas, bet geriau jų visai nedaryti.

Loginiai operatoriai

Loginės operacijos yra labai panašios į skaičių palyginamo operacijas. Visos loginės operacijos grąžina loginę reikšmę: true arba false. 4-10 lentelėje pateiktas loginių operacijų sąrašas.

Operatorius Aprašymas
! Neiginys
& Loginis AND
| Loginis OR
^ Loginis XOR
&& Sąlyginis AND
|| Sąlyginis OR
== Lygus
!= Nelygus
Op= Kombinacija priskyrimas ir operatorius
?: Sąlyginis operatorius
4-10 lentelė. Loginės operacijos.

Sąlygos operatorius yra vienintelis Java kalbos operatorius naudojantis tris operandus. Operatoriaus formatas yra a?b:c. Išraiška   a   yra apskaičiuojama ir gaunamas loginis rezultatas. Jeigu jis true , tuomet   grąžinamas b , kitu atveju - c. Pažiūrėkime iliustraciją:

  

int i; boolean cont=false; // Įprasta if komanda if (cont) i=5; else i=6; // Naudojant sutrumpinimą: i = (cont?5:6);

Kodas priskiria i arba 5 arba 6 priklausomai nuo loginio kintamojo cont reikšmės. Kai cont yra true ,i   priskiriama 5; kai jis false ,   i   priskiriama 6. Sąlyginis sutrumpintas operatorius atlieka šį priskyrimą trumpesniu būdu.

Operacijos su simboliais

Nėra nei vienos operacijos, kuri naudotų simbolius ir grąžintų simboliaus tipo rezultatą. Dauguma operatorių grąžins sveikąjį skaičių. Jeigu jūs norite, kad operacijos rezultatas būtų simbolis, turite nurodyti tipo pakeitimo operatorių (char). Kada simbolis yra naudojamas operandu, jis yra pakeičiamas sveikuoju skaičiumi. Tokio pakeitimo metu informacija neprarandama. Tarkime mes norime konvertuoti simbolį - raidę iš didžiosios į mažąją. A simbolio sveikoji reikšmė yra 98 ir ASCII ir unikode, o mažosios a - 65. Jeigu mes iš didžiosios raidės ir atimsime mažąją, gausime reikšmę, kurią galėsime panaudoti ir kitų raidžių konvertavimui. Tai iliustruosime pavyzdžiu:

  

char c='B'; c = (char) (c - ('A' - 'a'));

Operacijos su objektais

Su Java objektais palaikomos tokios operacijos: =, ==, != ir instanceof  . Pavyzdžiui sudėti du objektus negalima, nes bendru atveju neaišku koks turėtų būti šios operacijos turinys. Vienintelė išimtis yra eilučių atveju; tuomet ši operacija reiškia eilučių apjungimą.

Priskyrimo operatorius (=) naudojamas priskirti objekto rodyklę nurodytam kintamajam. Tai nesukuria objekto kopijos. Taip yra gaunamas kintamasis kitu vardu, tačiau jis yra tik sinonimas nuorodos, kurioje yra saugojamas objektas. Kai visi kintamieji neteks savo galiojimo lauko, objektas atlaisvinamas. Pasižiūrėkime į pavyzdį:

  

foo test = new foo(); foo test2 = null; test2 = test;

Šis kodas iliustruoja objektų priskyrimą. Pirma eilutė sukuria naują foo egzempliorių. Antra eilutė test2 objektui priskirią specialiąją tuščio objekto reikšmę. Kreipimasis į test2 dabar būtų negalimas ir gautume nullPointerException   klaidos pranešimą. Paskutinis operatorius sutapatina test ir test2. Dabar jau abudu kintamuosius galima naudoti, tačiau jie nereiškia skirtingus objektus, nes new foo() buvo panaudotas tik vieną kartą.

Objektai palaiko dvi palyginimo operacijas: lygus operaciją (==) ir nelygus operaciją (!=). Šios operacijos tikrina ar objektų kintamieji yra nuorodos į tą pačią atminties vietą. Du objektai turintys nuorodų kintamuosius į skirtinas vietas atmintyje bus visuomet nelygūs nepriklausomai nuo to ar visi jų metodai ir kintamieji yra vienodi ar ne. Pateiksime tokios situacijos pavyzdį:

  

foo testas = new foo(); foo test2 = new foo(); foo test3 = testas;

Naudojant šiuos priskyrimus, mes galime su nurodytais kintamaisiais sukurti lygybės santykių lentelę. 4-11 lentelė iliustruoja kokie objektai yra lygūs ir kokie - ne.

testas test2 test3
testas == != ==
test2 != == !=
test3 == != ==
4-11 lentelė. Objektų lygybė.

instanceof  ( egzemplioriaus tipo ) operatorius naudojamas nustatyti objekto tipą praginos metu. Jį panaudoti jums būtinai teks, jei norėsite sužinoti kokio tipo tapo objektas programos praginos metu. Tarkime turite shape klasės tipo kintamąjį. Tegul shape turi poklasę polygonShape ir jūs dirbate su kintamuoju, kuris pradžioje buvo paskelbtas shape tipo. Kaip jums sužinoti, ar praginos eigoje jis netapo polygonShape tipo? Pateiktas kodo fragmentas iliustruoja tokios problemos sprendimą.

  

shape shapeHolder; if (shapeHolder instanceof polygonShape) { polygonShape polygon = (polygonShape) shapeHolder; // darome ką nors su polygon }

Shape yra bendros formos klasė. Jeigu kintamasis shapeHolder yra specifinio tipo polygonShape, tai galime atlikti specifines šiam tipui operacijas. Kad galėtume dirbti su polygonShape tipu, mes susikurdami polygon kintamąjį apribojame kintamąjį shape iki polygonShape tipo.

Operacijos su eilutėmis

Mes jau minėjome, kad "Strings " yra Java klasė turinti hibridinių bruožų būdingų pirminiam tipui ir nuorodoms į objektus. Vartojimo prasme ji panaši į objektus, tačiau turi keletą nebūdingų nuorodoms savybių. Tenka kiek apgailestauti dėl šios išskirtinės eilučių padėties.

Mes pastebėjome, kad sumos ir skirtumo operacijos objektams neapibrėžiamos. Tačiau Java atveju eilutėms padaryta išimtis. Pamatę pirmą kartą dviejų eilučių sumą nesunkiai atspėsite kas turima omenyje šiuo atveju. Jei tas pats būtų pritaikyta kitų tipų objektams sumos turinys daugeliu atvejų būtų neakivaizdus. Todėl eilutėms ir padaryta išimtis, bet tai kiek griauna kalbos principą neapibrėžinėti sumos objektams.

Kaip ir buvo galima tikėtis, pliuso ženklas paprasčiausiai apjungia dvi eilutes. Jeigu vienas operandas yra ne eilutė, jis yra konvertuojamas į eilutės tipą ir tuomet apjungiamos eilutės. Visa tai atlieka kompiliatorius atlikdamas "+" operacijos perkrovos darbą. 4-12 lentelėje išvardintos "+" operacijos perkrovos taisyklės.

Operandas Taisyklė
 null  kintamieji Kiekvienas kintamieji kurios reikšmė bus  null  bus pakeistas eilute "null ".
Sveikasis skaičius Sveikasis skaičius bus konvertuotas į eilutę vaizduojančią dešimtainę skaičiaus išraišką. - ženklas pradės neigiamą skaičių ir nebus rašomi vedantieji nuliai, išskyrus 0 atvejį.
Slankaus kablelio Slankaus kablelio skaičiai bus konvertuojami į kompaktišką formą. Jeigu užrašo ilgis viršija 10 simbolių, jis bus užrašytas eksponentine forma. Neigiamas skaičius prasidės - ženklu.
Simbolis Simbolis bus konvertuotas į jai ekvivalenčią 1 simbolio ilgio eilutę.
Loginis Rezultatas bus arba "true"  arba "false"   eilutė priklausomai nuo loginio kintamojo reikšmės.
Objektas Objektams bus keičiamas toString() metodas.
4-12 lentelė. Eilutės kūrimo taisyklės.

Po konvertavimo gausime abudu operandus eilutės tipo ir jos bus apjungiamos. Keletas iliustracinių pavyzdžių:

  

String foo = "Sveikas "; String bar = "Pasauli"; int i = 42; boolean cont = false; String rezultatas = null; result = foo + bar; // = "Sveikas pasauli" result = foo + i; // = "Sveikas 42" result = foo + cont; // = "Sveikas false"

Naudojimo prasme tokia "+" Java interpretacija labai patogi ir tenka sutikti su Java autorių logika. Kokia prasmė galėtų būti "-" operacijos, kai bent vienas operandų yra teksto eilutė? Sunku pasakyti ir todėl Javoje tokia operacija negalima.

Dabar pakalbėkime apie == ir != operacijas. Išbandykite tokio kodo darbą:

  

String foo = "Sveikas"; String bar = "Sveikas"; if (foo == bar) System.out.println("Sutampa"); else System.out.println("Nesutampa");

Kodo darbo rezultatas bus "Sutampa". Taip ir tikėjotės :-). Pamėginkite dabar prognozuoti kito kodo darbo rezultatą:

  

class testString { String st = "Sveikas"; } class testString2 { String st = "Sveikas"; String st2 = "Sveikas"; public static void main(String Args[]) { testString testas = new testString(); testString2 test2 = new testString2(); if (test.st == test2.st2) System.out.println("Sutampa"); else System.out.println("Nesutampa"); if (test.st == test2.st) System.out.println("Sutampa"); else System.out.println("Nesutampa"); } }

Rezultatas bus daugeliui (manau, beveik visiems) netikėtas. Pirmu atveju bus atspausdinta "Sutampa", o antru - "Nesutampa". Paaiškinimas yra toks. Kompiliatorius atlieka atminties optimizavimo darbą. Todėl testString2 metode bus išskirta atminties tik vienam "Sveikas" egzemplioriui ir st ir st2 nurodys į tą pačią atminties vietą ir šiuo atveju == palyginimas duos  true  rezultatą.

Atkreipkite dėmesį, kad eilučių atveju == operatorius skirtas nepalyginti reikšmes, bet patikrinti ar operandai yra nuorodos į tą pačią atminties vietą. Kad palyginti eilučių visų simbolių seką, naudojamas metodas  equals . Pasižiūrėkime tokio palyginimo pavyzdį.

  

public static void main(String Args[]) { testString Testas = new testString(); testString2 Test2 = new testString2(); if (test.st.equals(test2.st2)) System.out.println("Sutampa"); else System.out.println("Nesutampa"); if (test.st.equals(test2.st)) System.out.println("Sutampa"); else System.out.println("Nesutampa"); } }

Apie eilutes mes dar pakalbėsime šio skyriaus "Strings " skyrelyje ir kituose skyriuose.

Paketai

  Paketas (package )   yra organizacinė priemonė numatyta Java kalboje tvarkyti klasių grupes. Konceptualiai paketas (package ) apjungia turinčias sąsają klases ir interfeisus. Jūs jau pažįstami su paketo pavyzdžiu, būtent, java.lang paketu. Šitas paketas yra neatsiejama Java kalbos dalis. Aplikacijų interfeisų programavimo (API) klasės yra taip pat apjungiamos į paketus. Jūs taip pat turite galimybę kurti savo paketus.

Pakete saugojamas vienas arba daugiau kodo failų. Kiekviename kodo faile pačioje pradžioje (neskaitant komentarų) turi būti paskelbtas package  operatorius. Kiekviename kodo faile gali būti paskelbta tik viena public  tipo klasė. Kada kodo failas yra sukompiliuojamas, klasės failas yra patalpinamas kataloge kurį nurodo paketo vardas. Paketo vardas reiškia katalogo vardą, kuriame pasviri brūkšniai yra pakeisti taškais. Pavyzdžiui, jeigu mes norime sukurti paketą kataloge ventana/awt/shapes, kiekvieno paketo kodo failo pradžioje turime panaudoti tokį package  apibrėžimą :

  

package ventana.awt.shapes;

Importavimas (import)

Kai mes turime paketą (package ), kaip galima panaudoti jo klases ir interfeisus? Vienas būdų yra užrašyti klasių pilną vardą. Tegul turime realizuotą paketą (package ), kuriame yra dvi klasės:  circle  ir  rectangle . Jeigu mes norime sukurti naują apskritimo klasės egzempliorių, galime panaudoti tokį kodą:   ventana.awt.shapes.circle circ = new ventana.awt.shapes();   Klasių panaudojimas rašant jų pilnus vardus gali varginti savo gremėzdiškais pavadinimais. Javos paketų importavimo (import) komanda sprendžia šią ilgų vardų problemą. Kai jūs importuojate su import paketą, toliau galite rašyti sutrumpintus importuoto paketo klasės ir interfeisų vardus. Tegul importavome apskritimo klasę iš  shapes  paketo. Tuomet galėsime tiesiog rašyti paketo klasės vardą nenurodant paketo vardo.

  

import ventana.awt.shapes.circle; class tryShapes { public static void main(String Args[]) { circle circ = new circle(); } }

Čia pateiktas sutrumpinto priėjimo prie paketo konkrečios klasės pavyzdys. Jeigu jums Java programoje bus reikalingos kelios klasės ir interfeisai, kurie yra patalpinti tame pačiame pakete, galite naudoti sutrumpintą kelių katalogų ir vardų žymėjimą  wildcard . Tokiame žymėjime žvaigždutė pakeičia visus galimus klasių ir interfeisų vardus. Pavyzdžiui naudotis visomis paketo  shapes  klasėmis galėsime pradėdami savo klasės kodą taip:

  

import wentana.awt.shapes.*;

Nemanykite, kad toks paketo importavimas padidins jūsų kodo dydį. Taip yra tik iškviečiamas paketo turinys į kompiliatoriaus simbolių lentelę, kurią kompiliatorius naudoja ieškant klases ir interfeisus į kuriuos kreipiatės savo programoje. Jūs galite naudotis ir trumpuoju ir ilguoju klasių vardų variantu. Dažniausiai praktiškai naudojamas trumpasis variantas, tačiau kartais jūs būsite priversti panaudoti ilgąjį variantą, kai atsiras tuo pačiu vardu pavadintos klasės skirtinguose paketuose, kuriuos jūs importuosite su  import  komanda.

Klasės

Mes jau kalbėjome apie klases ankstesniuose skyriuose. Dabar mes paliesime esminius sintaksės momentus. Kalbant apie klases labai pravartu pirma įsisavinti 3 skyriaus sąvokas, kur buvo kalbama apie Java objektinį programavimą. Jei objekto sąvoka jums neaiški, kalbėti apie klases maža prasmės.

  Klasė   yra pagrindinis darbinis Java programos blokas. Ji sudaryta iš duomenų ir metodų. Metodai apibrėžia būdus keisti ir sąveikauti su apgaubtais klasėje duomenimis. Padarydami vieną vienetą, kuriame apjungiami ir duomenys ir būdai juos keisti, mes padidiname mūsų kodo pakartotiną panaudojamumą ir pageriname programų palaikomumą.

Konstruktoriai

Java,  konstruktorius  yra vadinamas specialus metodas sukuriantis objektų naujus egzempliorius. Konstruktorius yra klasės metodas, kurio vardas sutampa su klasės vardu ir kuriame nenurodomas grįžties (return ) tipas. Jūs galite turėti daugelį konstruktorių, bet visi turi skirtis savo unikaliu parametrų skaičiumi ar jų parametrų tipų seka. Pateiksime klasės pavyzdį, kuriame apibrėžiama keletas konstruktorių:

  

class foo { foo() {...} // konstruktorius be parametrų foo(int n) {...} // kviečiant reikalaujamas vienas int   parametras foo(String s) {...} // kviečiant reikalaujamas vienas eilutės tipo parametras }

Čia visi trys konstruktoriai turi skirtingą parametrų skaičių arba skiriasi parametrų tipų sekos.

Destruktoriai

Kiekviena klasė gali turėti tik  vieną  destruktorių. Destruktorius  iškviečiamas kada objektą naikina šiukšlių surinkėjas ( garbage collector ). Taigi jūs negalite būti užtikrintas kada destruktorius bus panaudojamas. Destruktorius tinkama vieta patalpinti failų uždarymus ir čia naudinga atlaisvinti tinklo resursus. Destruktoriuje nebūtų protinga paskelbti vartotojo informacijos įvedimą arba sąveikauti su kitais objektais.

Destruktorius Javoje vadinamas  finalize . Jis neturi grįžties (return ) tipo ir neturi parametrų. Mes galėtume pridėti destruktorių į savo klasę foo  tokiu būdu:

  

class foo{ finalize() {...} // daro kai kurias resursų atlaisvinimo operacijas }

Klasės modifikatoriai

Klasės modifikatorius gali būti abstract  (abstraktus) , final  (nekeičiamas, neturintis vaikų) arba public   (vieša). Modifikatoriai turi būti rašomi prieš klasės raktažodį. Mes galime nustatyti klasės foo  modifikatorių tokiu būdu:

  

public final class foo{...}

  public     klasės gali būti panaudotos iš kitų paketų. Jeigu klasė yra ne public  , ją gali panaudoti paketas kuriame klasė paskelbta. Vieno failo kode galite paskelbti tik vieną public  klasę. Todėl failo kode gali būti tik viena public   klasė arba interfeisas.

  final     modifikatorius pažymi, kad ši klasė negali būti praplėsta. Kai kuriuos Java API klasės yra paskelbtos final . Pavyzdžiui, masyvas ( Array ) ir eilutės ( Strings ) klasės yra final , nes jos yra hibridinės klasės. Kitaip tariant jos nėra klasikiniai objektai, kuriuos mokėtų pilnai palaikyti kompiliatorius ir šiuo atveju Java autoriai buvo priversti juos paskelbti final . Apskritai, reikia vengti skelbti klases final , nes tuomet jūsų klasės negali turėti poklasių. Objektiniame programavime tokia savybė nepageidautina, nes kiti negalės paveldėti jūsų klasės funkcionalumo. final   modifikatorius naudingas kuriant nekintamus metodus, kurių nėra prasmės perdarinėti.

Paskelbdami klasę abstrakčia (abstract ), jūs pasakote kompiliatoriui, kad joje bus vienas arba keli abstract  metodai. abstract  metodas neturi kodo ir jis turi būti realizuotas vėliau poklasėse. Ji negali būti inicijuota, bet gali ir turi būti praplėsta. Kiekviena abstract  klasės poklasė turi realizuoti abstrakčius metodus arba pati turi būti paskelbta abstract tipo. Abstrakčių klasių mechanizmas leidžia struktūriškai programuoti. Abstract  klasė vadinamu interfeisu ; apie tai plačiau skyrelyje "Interfeisai".

extends (praplečia ) raktažodis

Paveldėjimui paskelbti naudojamas extends (praplečia) raktažodis. Kiekviena klasė gali praplėsti ne daugiau vienos klasės. Tačiau panaudojant interfeisus galima imituoti daugelio klasių paveldimumą.

Visi Java objektai turi tą patį tėvą vadinamą objektu. Jeigu jūs nenustatote objekto tėvo, jo nutylimasis tėvas yra klasė  Object . Kad apibrėžti klasės tėvą, naudojamas extends (praplečia ) raktažodis. Jeigu mes turėtume klasę foo  , galėtume sukurti jos poklasę  bar :

  

class bar extends foo{...}

Poklasė paveldi klasės metodus ir kintamuosius. Jūs galite apibrėžti iš naujo arba maskuoti metodą arba kintamuąjį sukurdami metodą ar kintamąjį su tuo pačiu vardu. Kad panaudoti užmaskuotą identifikatorių, jums reikia naudoti super  kintamąjį. Šis kintamasis nurodo į klasės tiesioginį tėvą. Jeigu foo  turi metodą vardu  test , tai jį užmaskuoti  bar  klasėje galėsime taip:

  

class bar extends foo{ void test() { super.test(); // iškviečia tėvo test metodą // ir atlieka kitus veiksmus } }

Jeigu praplečiant klases organizuosite ciklinį paveldėjimo santykį, gausite kompiliavimo klaidą. Klasė  B  negali būti  A  poklasė jeigu  A  jau yra  B  poklasė.

implements (realizuoja )

Klasės gali implementuoti net kokį interfeisų skaičių. Interfeisas yra klasės kurios visi metodai yra abstraktūs (abstract ). Paskelbiant klasę implements raktažodis yra rašomas paskutiniu. Pilna klasės paskelbimo sintaksė yra tokia:

  

  klasės_modifikatoriai   class   klasės_vardas   extends   tėvo_vardas   implements   interfeiso_vardas {...}  

Visi elementai išskyrus  class  raktažodį ir klasės vardą yra nebūtini. Jeigu klasė realizuoja interfeisą, joje būtina realizuoti metodus apibrėžtus interfeise. Vienintelė šios taisyklės išimtis yra abstract  klasės atvejis; šiuo atveju klasės vaikai privalo realizuoti interfeiso metodus.

Tegul turime interfeisą vadinamą shapeInterface, kuris turi du metodus -  draw  ir  erase . Tuomet mes galėtume apibrėžti klasę vardu  shape , kuri realizuotų interfeiso metodus:

  

class shape implements shapeInterface { void draw() {...} void erase() {...} }

Po  implements  galima vienai klasei nurodyti daugelio interfeisų vardus atskiriant juos kableliais. Programuotojas privalo realizuoti visus interfeisuose nurodytus metodus. Tarkime turime du interfeisus: shapeInterface ir moveableInterface. Tuomet galėtume apibrėžti klasę dragDrop, kuri realizuotų abudu šiuos interfeisus:

  

class dragDrop implements shapeInterface, moveableInterface {...}

Interfeisų sintaksę aptarsime vėliau skyrelyje "Interfeisai".

Kintamųjų modifikatoriai

Apibrėždami klasės kintamuosius galite nurodyti jų modifikatorius. Šie modifikatoriai įtakoja kokios kitos klasės gali panaudoti klasės kintamuosius, kai kurias daugiagijiškumo operacijas. Kintamuosius galima paskelbti static  arba final  . Kiti kintamųjų modifikatoriai yra tokie: public , private , protected , static , final , transient  ir volatile .

Kintamieji gali būti paskelbti public , protected , nutylimas "friendly" (kuris yra nerašomas) arba private .

public     kintamasis gali būti panaudotas bet kurioje paketo kuriame jis buvo paskelbtas klasėje ir bet kurioje kitoje klasėje. Tai mažiausiai apribojantis (visai neribojantis) modifikatorius.

protected   tarkime klasės C kintamasis yra prieinamas paketo klasėms, kuriame yra C klasė, ir klasės C poklasėms. Šis modifikatorius apriboja kintamojo panaudojimą kitų paketų klasėms, išskyrus tą atvejį, kai jos praplečia klasę C.

Jeigu C klasės kintamojo modifikatorius nenurodytas, kartais jis vadinamas "friendly". Toks kintamasis yra prieinamas paketo (kuriame yra C klasė) klasėms.

private  kintamasis pasiekiamas tik tos pačios klasės metodams. Tai labiausiai ribojantis kintamojo panaudojimą modifikatorius. Klasės poklasės taip pat negali panaudoti private  kintamuosius.

Čia pateikiamas pavyzdys, kuriame panaudoti visi keturi modifikatoriai:

  

class circle { public String className; protected int x,y; float spindulys; private int graphicsID; }

Jeigu kintamasis paskelbtas static , tai kompiliatorius realizuoja tik vieną jo egzempliorių ir jis turi tą patį vardą, kuriuo jis bovo paskelbtas. static kintamajam vieta išskiriama kompiliavimo metu. Todėl su tokiu kintamuoju iš karto galima dirbti nenaudojant  new  operatoriaus. Static kintamųjų pavyzdžių rasite matematinių klasių pakete  Math . Pavyzdžiui taip galime atspausdinti konstantos p reikšmę:

  

System.out.println("PI:" + Math.PI);

final  modifikatorius nustato, kad kintamojo reikšmė negali būti pakeista. Šis kintamasis iš karto turi būti inicijuojamas ir bet kuris bandymas į keisti iššauks kompiliavimo klaidą. final  modifikatorius paprastai naudojamas apibrėžti konstantas. Konstantos dažniausiai nurodomos tokiu modifikatorių rinkiniu: public static final . Mes galėtume paskelbti konstantą mūsų klasėje foo  taip:

  

class foo { public static final int atsakymas = 42; }

transient   ir volatile  modifikatoriai yra naudojami gijų programavime. Jie naudingi optimizuojant kodą. Raktažodis transient  kol kas rezervuotas vėlesnėm Java kalbos versijoms.

  volatile     kintamieji yra keičiami gijose asinchroniškai. volatile   kintamasis yra iškviečiamas naujai iš atminties ir išsaugojamas naujai atmintyje po kiekvieno jo panaudojimo. Šie du modifikatoriai yra rezervuoti ateičiai, juos galima naudoti ir Java 2 kalboje.

Metodų modifikatoriai

Metodų galimi modifikatoriai išvardinti 4-13 lentelėje. public  , nutylimasis, protected   ir private   yra modifikatoriai analogiški klasių kintamųjų atitinkamiems modifikatoriams. Jie nurodo kokios klasės gali naudoti metodą.

public   protected   private   static  
abstract final   native   synchronized  
4-13 lentelė. Metodų modifikatoriai.

  static     modifikatorius padaro metodą pasiekiamą net tuo atveju, kai klasė nėra inicijuota. static   metodas netiesiogiai paskelbtas final  ; todėl metodų negalima perkrauti kitais metodais. Viduje static  metodo galima panaudoti tik tuos klasės narius, kurie taip pat yra static .

abstract  metodo modifikatorius paskelbia, kad šis metodas bus realizuotas vėliau poklasėje. Jeigu jūs paskelbėte kokį nors klasės metodą abstrakčiu (abstract ), toks metodas negali būti toje klasėje aprašytas. Jeigu visi klasės metodai yra abstract , jums verta pamąstyti ar nebūtų geriau šią klasę apiforminti interfeisu.

final   metodo modifikatorius paskelbia, kad šis metodas negali būti perrašytas klasės poklasėse. Optimizuojantys kodą kompiliatoriai final   metodų kodą gali tiesiogiai įterpti į kompiliuojamąjį kodą ir taip sąskaita ilgesnio kompiliuoto kodo pagreitinti programos vykdymą. Tokia praktika dažnai taikoma C++ kalboje.

  synchronized     raktažodis naudojamas pažymėti metodus, kurie reikalauja gijų sustabdymo prieš vykdant metodą. Apie tai plačiau kalbėsime skyriuje "Gijų programavimas".

Metodų perkrova

Jeigu jūs norite parašyti kodą, kuris naudojant to paties pavadinimo metodą apdorotų parametrus skirtingai, jums reikia perkrauti metodą. Gana dažnai tokia praktika taikoma klasių konstruktoriams. Lygiai tą patį galite atlikti ir su metodais, tik negalite perkrauti destruktoriaus. Reikalas tas, kad destruktorius turi fiksuotą vardą ir neturi parametrų.

Metodas perkraunamas panaudojant tą patį vardas ir tą patį grįžties tipą su skirtingomis parametrų tipų sekomis. Kiekvienas perkrautas metodas turi būti unikalus; unikalumas apibrėžiamas parametrų skaičiumi ir jų tipais. Parametrų vardai neturi įtakos vienačiai. Pavyzdžiui, pateiktas kodas nebus sukompiliuotas:

  

class foo { foo(int i) {...} // nebus sukompiliuota, foo(int j) {...} // nes metodų parametrų tipų sekos nesiskiria }

Pateiktas kodas turi du metodus, kurie turi tą patį parametrų sąrašą - vieną int  tipo kintamąjį. Tokia metodo perkrova yra klaidinga.

Pakeitus parametrų sąrašo tipus, metodo perkrova bus galima:

 

class foo { foo(int i) {} foo(byte j) {} }

Šitas kodas bus sukompiliuotas ir bus pasiruošęs atlikti  foo  metodą, jei bus perduotas vienas  int  arba  byte  parametras. Tačiau gausite kompiliavimo klaidą, jei bandysite tam pačiam metodui perduoti short   arba long   tipo kintamąjį. Taigi Java neatlieka parametrų tipų konvertavimo ir šia savybe skiriasi nuo C/C++ kalbų.

Nuorodos tipo kintamųjų konvertavimas

Visos nuorodos į objektus ir interfeisus padaromos panaudojant  nuorodų kintamuosius  ( reference variables ), kurie kartais vadinami  rodyklėmis  ( pointers ). Jūs galėjote anksčiau kur nors perskaityti, kad Java nenaudoja rodyklių, tačiau tai ginčytinas teiginys. Java neturi rodyklių aritmetikos, bet savo esme nuorodų kintamieji yra rodyklės. Kad Java būtų saugesnė ir labiau nepriklausoma nuo platformų, jos kūrėjai nutarė palikti tik vieną būdą keisti nuorodos reikšmę; tas būdas yra paprastas priskyrimo operatorius.

Nuorodų kintamuosius apibrėžti lengva. Paskelbkite klasės arba interfeiso tipo kintamąjį, bet nepriskirkite jam reikšmės su  new  operatoriumi. Tuomet šiam kintamajam galėsite priskirti to paties tipo anksčiau sukurtus kintamuosius. Paskelbkime porą nuorodų kintamųjų; vieną tipo myClass klasės, kitą - shapes tipo interfeisą.

  

myClass myRef; shapes myShapes;

Priskiriant nuorodų kintamiesiems reikšmes reikia laikytis tam tikrų taisyklių. Visuomet leidžiama nuorodos kintamajam priskirti to paties tipo kintamąjį. Priskiriant vieno tipo nuorodai kito tipo nuorodą, interfeisą ar masyvą kyla klausimas ar toks priskyrimas yra leidžiamas. Vienais atvejais toks priskyrimas leidžiamas, kitais leidžiamas, jei naudojamas tipo apribojimo (cast) operatorius, o dar kitais atvejais priskyrimas neleidžiamas niekuomet. Automatinio tipo konvertavimo taisyklės yra gana sudėtingos. Kai kurias taisykles mes paaiškinsime, bet bendru atveju geriau studijuoti Java kalbos specifikaciją, kurioje rasite atsakymą visais atvejais.

Jeigu sukuriate S klasės tipo nuorodos kintamąjį, šiai nuorodai galite priskirti tokius tipus:

Jeigu sukuriate nuorodos kintamąjį interfeisui S, kiekvienas jo priskyrimas turi realizuoti S. Tipų suderinamumas turi būti apibrėžtas praginos metu, nes S poklasė gali turėti realizuotą interfeisą.

Kitais priskyrimo atvejais galima naudoti  tipo apribojimo  ( cast ) operatorių. Jeigu naudojate cast operatorių, galite gauti praginos klaidą. Jūs turite būti garantuotas, kad praginos metu objektas bus apibrėžtas arba turite būti pasiruošęs apdoroti  castClassException  praginos klaidą.

Interfeisai

  Interfeisas   yra ekvivalentus klasei, kurios visi metodai yra paskelbti abstrakčiais (abstract ) ir kurių visi kintamieji paskelbti static  ir final . Kiekvienas metodas yra nerealizuojamas ir visi kintamieji yra konstantos. Kiekvienas interfeiso kintamasis turi būti inicijuotas (priskirta pradinė reikšmė) ir kintamieji negali būti paskelbti transient  arba volatile . Interfeiso metodai negali turėti modifikatorius final , native , static  ir synchronized .

Kiekviena klasė kurios antraštėje paskelbta, kad ji  implements (realizuoja ) interfeisą privalo realizuoti visus tame interfeise paskelbtus metodus. Interfeisas yra būdas kurti konceptualiai programas. Jis naudingas konstruojant objektų hierarchijas. Kai kurie programuotojai laikosi metodologijos pirma aprašyti visus interfeisus ir klases, nes tai palengvina kodų apjungimo problemos sprendimą. Vėliau, interfeisai yra realizuojami. Tokia maniera leidžia rašyti labiau abstraktų kodą, kuris vėliau yra lengvai praplečiamas.

Interfeisų apibrėžimas labai panašus į klasių apibrėžimą. Pagrindinis skirtumas yra tas, kad čia vietoje  class  naudojamas raktažodis  interface . Apibrėšime shapeInterface interfeisą, kuris turi du metodus: draw ir erase:

  

public interface shapeInterface { public void draw(); public void erase(); }

Dabar galime realizuoti keletą skirtingų formų naudojančių šį interfeisą. Vėliau galėsime sukurti duomenų struktūras kuriose yra shapeInterface tipo kintamieji. Nepaisant konkrečios realizacijos bus galima naudotis interfeise paskelbtais metodai. Interfeisas yra galinga programavimo priemonė ir ypač naudinga gerinant kodo panaudojamumą ir suprantamumą.

Masyvai ( Arrays )

 Masyvas   Array  yra hibridinis  pirminio  ir  objekto  tipas. Vizualiai jis primena objektą, bet turi specialią prasmę kompiliatoriui. Klasė  Array  yra paskelbta final , taigi jūs negalite jos praplėsti savo funkcionalumu.

Masyvas naudojamas saugoti grupėje panašią informaciją. Visi masyvo vienetai kompiliavimo metu turi būti to paties tipo. Jeigu masyvas sudarytas iš pirminio tipo elementų, visi elementai turi būti to paties pirminio tipo; jeigu jis sudarytas iš nuorodos tipo kintamųjų, visos jos turi būti vienodo tipo.

Masyvas panašus į objektą, nes prieš naudojant naują masyvą pirma jį reikia inicijuoti su  new  operatoriumi; dar daugiau - kiekvienas nuorodų tipo masyvo elementas taip pat turi būti inicijuojamas  new  operatoriumi. Šiuo atžvilgiu Java masyvai skiriasi nuo daugelio kitų kalbų masyvų, nes kitose kalbose masyvo elementų nutylimuoju inicijavimu pasirūpina kompiliatorius.

Java masyvai ženkliai skiriasi nuo daugumos kalbų masyvų. Sutaupysite daug laiko ateityje, jei jau dabar įsigilinsite į Java masyvų naudojimo subtilumus. Nemanykite, kad Java masyvai yra tie patys kaip C arba Paskalio kalbose. Jeigu esate susipažinę su  smallTalk , tuomet jums pasisekė - joje naudojami masyvai yra analogiški Java masyvams.

Masyvų sukūrimas

Masyvai yra inicijuojami naudojant  new  operatorių. Kiekvienas masyvo elementas yra atskiras objektas. Masyvas yra savotiškas konteineris, kuriame talpinami visi objektai, ir kuris suteikia patogų priėjimą prie konteineryje patalpintų elementų.

Paprasčiausias masyvas yra vienmatis masyvas, kuriame talpinami pirminio tipo kintamieji. Paskelbkime ir inicijuokime sveikųjų skaičių masyvą, kuris turėtų 5 elementus:

 

int nums[] = new int[5];

Iš pateikto pavyzdžio aiški dauguma masyvo paskelbimo ir inicijavimo sintaksės taisyklių. Laužtiniai skliausteliai po tipo identifikatoriaus nurodo kompiliatoriui, kad šis kintamasis skirtas masyvui, kurio elementai turės pradžioje nurodytą tipą (mūsų pavyzdyje  int  tipą).  new  operatorius iškviečia nurodytą skaičių konstruktorių (pavyzdyje - 5) inicijuoti kiekvienam masyvo elementui. Turėdami tai omenyje nesunkiai suprasite ir daugiamačių masyvų sintaksę (apibrėžimo taisykles) ir semantiką (prasmę).

Java masyvai turi turėti bent vieną apibrėžtą dimensiją. Likusias galima apibrėžti praginos metu. Kad paskelbti ir inicijuoti dvimatį masyvą, galime parašyti tokį kodą:

 

class tarray { public static void main(String args[]) { int numsList[][] = new int[2][]; // Kitą dimensiją apibrėžiame vėliau numsList = new int[2][10]; for(int i=0; i< 10 ;i++) { numsList[0][i] = i; numsList[1][i] = i; } for(int i=0; i< 10; i++) { System.out.print(numsList[0][i] + " "); System.out.println(numsList[1][i]); } } }

Šitas kodas sukuria numsList masyvą, kurio nurodytas tik vienas matavimas. Mes galime apibrėžti kitą matavimą vėliau. Yra svarbu atsiminti, kad konstruktorių galime kviesti dėl kiekveino masyvo elemento. Šią Java kalbos savybę galime panaudoti sukuriant nestačiakampius masyvus. Sukurkime trikampį masyvą:

 

int[][] createArray(int n) { int[][] numeriai = new int[n][]; for(i=0; i< n; i++) { nums[i] = new int[i+1]; } return numeriai; }

Šis kodas sukuria trikampį masyvą iš n elementų. Pirmas elementas turės vieną elementą, kitas du elementus ir paskutinis turės n elementų. Toks masyvo elementų inicijavimo būdas atveria daug papildomų galimybių. Taigi prireikus bet kokios susietų duomenų struktūros galime panaudoti tam reikalui masyvą.

Masyvų inicijavimas

Masyvai gali būti inicijuojami jų sukūrimo metu parašant tarp riestinių skliaustų {} norimas pradines reikšmes. Šiuo atveju jums nereikės nurodyti bendrą masyvo elementų skaičių, nes kompiliatorius sukurs lygiai tokio ilgio masyvą kiek reikia patalpinti visas skliausteliuose nurodytas pradines reikšmes. Kad inicijuoti daugiamačius masyvus, inicijavimo metu jūs galite panaudoti vidinį tiesioginį inicijavimą, .

Pateiksime paprastą tiesioginio masyvo inicijavimo pavyzdį.

  

int nums[] = {1,2,3,4,5};

Inicijuojant dvimatį masyvą reikės vidinių inicijavimo riestinių skliaustų. Pateiksime paprastą tokio inicijavimo pavyzdį:

  

int mums[][] = {{1,1},{2,2},{3,3},{4,4},{5,5}};

Kaip matote, inicijuoti vienmatį ar dvimatį masyvą yra lengva. Inicijuojant daugiamačius masyvus naudojama analogiška sintaksė, tik šiuo atveju sunkiau susikurti vizualią masyvo interpretaciją.

Masyvų panaudojimas

Masyvo elementų indeksavimui galima panaudoti byte , short , int  arba char  tipų kintamuosius. Jūs negalite masyvo indeksuoti su long , slankaus kablelio arba logine reikšme. Jeigu jums reikia panaudoti vieną šių tipų, jūs turite atlikti tipo apribojimą, t.y. panaudoti  cast  operatorių.

Masyvo indeksas gali kisti nuo nulio iki masyvo ilgio minus vienas. Jūs galite rasti kiekvienos masyvo dimensijos ilgį panaudojant  length  kintamąjį. Pateiksime masyvo  length  kintamojo panaudojimo pavyzdį.

 

long sum(int[] list) { long result=0; for(int i=0; i< list.length; i++) { result = rezultatas + list[i]; } return rezultatas; }

Šitas kodas sudės bet kokio ilgio sveikųjų skaičių masyvo elementus. Tai pasiekiama panaudojant  length  kintamąjį, kuris parodo masyvo elementų skaičių.

Java tikrina ar masyvo indeksas priklauso galimai jo kitimo sričiai. Todėl jei indeksas bus neigiamas ar didesnis arba lygus už masyvo ilgį bus gaunama  arrayIndexOutOfBoundsException  klaida.

Java masyvai yra galingas instrumentas, bet už tai tenka sumokėti tam tikrą kainą. Kai kurie kompiliatoriai optimizuoti stačiakampiams masyvams, kiti - ne. Reikia suprasti, kad nestačiakampiai masyvai kiek sulėtina programos darbą, bet tai yra pažįstama dilema - programuojant dažnai tenka rinktis tarp programavimo kodo paprastumo ir programos efektyvumo jos vykdymo greičio prasme.

Programos vykdymo eigos kontrolė

Dauguma kompiuterio programų turi galimybę keisti jos vykdymo eigą. Tokios kalbos priemonės vadinamos  valdymo komandomis . Tarp jų yra mums pažįstama  if-else  komanda ir ciklo komanda  for . Visos kompiuterių programavimo kalbos turi valdymo komandas ir daugelis jų jums turi būti pažįstamos. Mes pakalbėsime apie kiekvienos detales, nors jūs esate laisvi pasirinkti tik tų aprašymą, kurias jūs nepažįstate arba nepakankamai gerai žinote. Trumpai apie valdymo komandų struktūrą:

 

if (boolean) statement1; else statement2; for(išraiška; loginė išraika; išraiška) komanda; while(boolean) komanda; do komanda; while(boolean); break žymė; continue žymė; return išraiška; switch(expression) { case reikšmė : komanda; .... default : komanda; }

if-else komanda

Daugiausiai žinoma valdymo komanda yra if - else   konstrukcija. Po  if  einanti loginė išraiška yra apskaičiuojama ir gaunamas loginis rezultatas true  arba false . Rezultatas true  priverčia vykdyti komandą stovinčią po  if , o false  atveju bus vykdoma po else   parašyta komanda. Jeigu jums nereikia false  atveju atlikti jokių veiksmų, tiesiog nerašote  else  ir problema išspręsta. Pateiksime paprastą if - else   panaudojimo pavyzdį:

 

if (done == true) System.out.println("atlikau"); else System.out.println("tęsiu");

Jūs galite if-else komandas parašyti pakartotinai.  if  loginės išraiškos bus apskaičiuojamo paeiliui pradedant nuo kairiosios  if  tol, kol nebus rasta pirmoji true  reikšmė. Jeigu nei viena  if  loginių išraiškų nėra true , tuomet bus vykdoma else  komanda. Remiantis tokia konstrukcija galima atspausdinti tinkamą duotai temperatūrai tekstą:

 

int temp; if (temp < 0) System.out.println("Jo, šiandien šaltoka."); else if (temp > 100) System.out.println("Vanduo jau verda?"); else System.out.println("Gera šiandien diena!");

Jūs galite pažymėti tik vieną vykdomą po sąlygos tikrinimo komandą. Ką daryti, jei jums reikia atlikti keletą komandų? Šiuo atveju galima pasinaudoti bloku. Bloku vadinama grupė komandų, kurios patalpintos tarp riestinių skliaustų poros {}. Programos eigos valdymo operatorių atveju vieno bloko komandos yra atliekamos visos, jei bloke nepanaudoti specialūs anksčiau užbaigiantys darbą bloke operatoriai. Pasižiūrėkime pavyzdį:

 

int itemCount; boolean checkout; if (itemCount <= 10) { System.out.println("Ačiū, kad pradėjote patikrinimą"); checkout = true; } else { System.out.println("Pateikti galima ne daugiau 10 vienetų!"); checkout = false; }

Paskalyje blokai yra apibrėžiami begin/end pora. Java naudoja C/C++ susitarimą panaudoti blokui žymėti riestinius skliaustus.

Atkreipkite į vieną if-else komandos naudojimo problemą. Sudėtingesniais atvejais iškyla neaiškumas kuri else šaka bus skaičiuojama. Pateiktas kodas iliustruoja šią problemą:

 

int prekėsKaina, turiuPinigų; boolean šaliaNėraŽmonos; if (prekėsKaina <= turiuPinigų) // neteisinga kodas if (šaliaNėraŽmonos == true) System.out.println("Pirksiu"); else System.out.println("Nepakanka pinigų");

Pateiktas pavyzdys veiks ne taip, kaip tikisi daugelis nepatyrusių programuotojų. Čia iškyla problema: neaišku kuriam  if  skirta  else  šaka.  else  šaka yra visuomet asocijuojama su paskutiniu if ir todėl čia spausdinamas tekstas yra nekorektiškas. Problema yra sprendžiama panaudojant riestinius skliaustus su kuriais tiesiogiai nurodote if-else galiojimo lygį. Pataisykime savo nekorektišką kodą:

 

int prekėsKaina, turiuPinigų; boolean šaliaNėraŽmonos; if (prekėsKaina <= turiuPinigų){ if (šaliaNėraŽmonos == true) System.out.println("Pirksiu"); } else System.out.println("Nepakanka pinigų");

Teisingai panaudoti blokai daro jūsų kodą lengviau skaitomu ir apsaugoja nuo subtilių loginių klaidų. If-else komanda naudinga programavimo priemonės, tik reikia atidžiai sekti visas if-else poras.

while   ir do-while komandos

 while     ir   do-while   komandos naudojamas dviem specifiniais ciklų atvejais. while   komanda naudojama, kai jums tinka ir toks atvejis, kai ciklo kamienas nebus įvykdytas nei karto. Palyginimo išraiška apskaičiuojama prieš ciklo operatoriaus įvykdymą. Kada ši išraiška yra false , ciklas užbaigiamas. Kad negauti be galo vykdomą ciklą, jūs turite pakeisti loginės išraiškos kintamųjų reikšmes ciklo kamieno viduje. Tarkime  rezult()  metodas grąžina loginę reikšmę. Tuomet galima tokia  while  konstrukcija:

 

while( result() ) { // Vykdomos ciklo kamieno komandos .... }

Šitas ciklas bus vykdomas tol, kol funkcija rezult() grąžins false  reikšmę. Jeigu ji pačioje pradžioje grąžina false , ciklas nebus įvykdytas nei karto. Jeigu mes norime, kad ciklo kamienas būtų vykdomas mažiausiai kartą, galime naudoti  do-while  ciklą. Šio tipo ciklas bus vykdomas bent kartą, nepaisant jo palyginimo išraiškos. Naudojant tą pačią loginę funkciją galėsime parašyti naują kodą, kur būsime garantuoti, kad ciklo kamieno komandos bus vykdomos bent kartą:

 

do { // Vykdomos komandos .... } while ( result() );

while   ir  do-while  komandos naudojamos pakartotiniems skaičiavimams atlikti. Yra dar viena ciklo konstrukcija naudojanti raktinį žodį  for . Ši konstrukcija savo funkcionalumu nesiskiria nuo pirmų dviejų, tačiau  for  panaudojimas daro jūsų kodą lengviau skaitomu.

for komanda

 for  komanda yra galingas ciklinių skaičiavimų organizavimo instrumentas. Po  for  operatoriaus ciklo išraiškos pradžioje yra inicijuojamas ciklo kintamasis (skaitliukas), toliau eina palyginimo išraiška ir tuomet ciklo kintamojo keitimo išraiška. Tipiniu atveju ciklo kintamasis (skaitliukas) yra padidinamas arba sumažinamas vienetu. Pateiktas pavyzdys paeiliui atspausdins skaitliuko reikšmes nuo 0 iki 4:

 

for(int i=0; i< 5; i++) { System.out.println(i); }

Trys ciklo išraiškos apskaičiuojamos skirtingais būdais. Pirma išraiška (inicijavimo segmentas) įvykdomas vieną kartą pačioje ciklo vykdymo pradžioje. Antroji išraiškos tikrinimo dalis atliekama cikliškai kiekvienos ciklo iteracijos pradžioje įskaitant ir patį pirmąjį kartą. Paskutinė trečioji dalis įvykdoma po ciklo kamieno užbaigimo; šioje dalyje standartiniu atveju ciklo išraiškos kintamasis padidinamas arba sumažinamas vienetu.

Iš pateikto pavyzdžio matyti, kad ciklo skaitliuko kintamasis  i  buvo paskelbtas ciklo išraiškos viduje, t.y. buvo panaudotas operatorius  int i; . Tai yra leidžiama, nes ciklo išraiška laikoma nauju vidiniu programos bloku ir nepriklausomai nuo to ar ciklo kintamasis buvo paskelbtas ar ne jūs turite teisę jį paskelbti ciklo išraiškos viduje. Ciklo skaitliuko paskelbimas išraiškos viduje yra rekomenduotinas, nes tai apsaugoja nuo sunkiai aptinkamų anksčiau paskelbtų tuo pačiu vardu kintamųjų reikšmių neprognozuoto pakeitimo. Taip pat toks kodas yra lengviau skaitomas.

Toliau ciklo išraiškos antroje dalyje yra palyginimo išraiška. Ji grąžina loginę reikšmę. Skirtingai nuo C/C++ kalbų išraiška negali grąžinti sveikojo skaičiaus. Reikalas tas, kad C/C++ kalbose laikomasi susitarimo, kad bet kokio tipo sveikojo skaičiaus reikšmė 0 gali būti naudojama logine  false  reikšme, o visi kiti sveikieji skaičiai atitinka  true . Java atveju toks dvilypis sveikųjų skaičių panaudojimas draudžiamas. Taip yra pasiekiamas didesnis Java kodo skaitomumas.

Visos ciklo antrosios dalies išraiškos turi grąžinti loginę reikšmę. Čia neleidžiama panaudoti sveikosios išraiškos, nes Java sveikojo skaičiaus niekuomet neinterpretuoja logine reikšme.

Paskutinė  for komandos išraiškos dalis apskaičiuojama cikliškai kiekvieną kartą pabaigus vykdyti ciklo kamieno komandas. Ciklo išraiškos skaitliukas nebūtinai turi būti keičiamas vienetu; su  for  komanda galima imituoti kitas ciklo konstrukcijas. Pateiksime tokio  for  panaudojimo pavyzdį:

 

boolean cont = true; .... for(; cont == true;) { // Komandos kurios atlieka kokius nors veiksmus ... // Naujos cont reikšmės apskaičiavimo komandos ... }

while   komanda turi palyginimo komandą, kurios patikrinimu prasideda ciklas. Jeigu palyginimo reikšmė false , ciklas nebus vykdomas nei karto. Naudojant  for  ciklo išraišką, kurioje praleista inicijavimo dalis imituojamas while   ciklas. Pastebėkime kad kabliataškis nėra praleidžiamas, nors ciklo skaitliuko inicijavimo operatorius šiuo atveju yra praleistas.

break   ir continue komandos

Java turi galimybę lanksčiai reguliuoti ciklo kamieno vykdymą. Tarkime jūs turite ciklą kuris paprastai vykdomas 10 kartų, bet ketvirtadieniais jį reikia atlikti tik keturis kartus. Panašaus tipo atvejais naudojami programos vykdymo eigą keičiantys Java operatoriai break   ir continue.

break   komanda naudojama perkelti programos vykdymą už ciklo konstrukcijos( for, do, while, switch ) pabaigos. Ciklas bus užbaigiamas nepaisant jo palyginimo reikšmės ir bus vykdoma einanti po ciklo pabaigos komanda. Užbaigiant while   ciklą galime panaudoti break  komandą, be kurios ciklas gali ir niekada nesibaigti:

 

int i=0; while(true) { System.out.println(i); i++; if (i > 10) break; }

Šiuo atveju bus paeiliui atspausdinti sveikieji skaičiai nuo 0 ir iki 10.

continue komanda panaši į break  komandą. continue komanda priverčia programos vykdymą tęsti praleidžiant po sutikto  continue  ciklo kamieno komandas. Pavyzdžiui pateiktame kode paprastai išvengiama dalyba iš nulio:

 

for(int i = -10; i< 10; i++) if (i == 0) continue; System.out.println(1/i); }

Šis ciklas neatliks dalybos, kai i == 0. Atkreipkime dėmesį, kad i++ bus apskaičiuojamas ir tuo atveju, kai kamieno vykdymą nutrauks  continue  operatorius. Jei taip nebūtų, tai parašytas kodas būtų vykdomas be galo, nes nepakistų  i  reikšmė 0.

Ir break  ir continue komandos gali naudoti valdymo perdavimą žyme ( label ) pažymėtai programos daliai. Žymės sintaksė yra tokia: pirma rašomas žymės vardas, po to dvitaškis ir toliau einantis programos kodas. Praktiškai tai atrodo taip:

 

loop: for(int i=0; i< 10; i++) { }

Žymių ir valdymo operatorių panaudojimas imituoja daugeliui pažįstamą kitų kalbų  goto  operatorių, tačiau Java atveju šis operatorius tiesiogiai nenaudojamas. Tarkime susidūrėte su situacija, kai jums reikia nutraukti daugelio įdėtų ciklų vykdymą, kai tik bus rastas ciklo elementas su reikšme 5. Todėl mes pažymėsime išorinį ciklo operatorių žyme ir perduosime jos pabaigai valdymą, kai bus rasta masyvo reikšmė 5:

 

int i=-1,j=-1; int nums[][] = new int[5][5]; boolean found = false; loop: for(i=0; i<5; i++) { for(j=0; j< 5; j++) { if (nums[i][j] == 5) { found = true; break loop; } } } if (!found) System.out.println("Reikšmė nerasta"); else System.out.println("Rasta taške " + i + "," + j);

Šitas kodo fragmentas programavimo kalbų pradinukams gali atrodyti nesuprantamas, nes jame integruotai panaudoti ciklų, masyvų ir vykdymo eigos valdymo programavimo elementai.

return   komanda

return  komandos esmė panaši į break  , tik ja yra užbaigiamas ne ciklo bet metodo vykdymas. Papildomai po return gali būti nurodyta išraiška, kuri bus apskaičiuota ir grąžinta iškvietusiajam metodui. Užprogramuosime kėlimą n-uoju laipsniu:

 

class power { public int toN(int base, int n) { int result=base; for(int i=0; i< N - 1; i++) result = rezult * base; } return rezult; } }

Šitas kodas apskaičiuoja pagrindo  base  n-ąjį laipsnį. Čia panaudota return  komanda, kad grąžinti apskaičiuotą rezultatą. Kitas kodas po return  komandos nebus vykdomas. return   komanda grąžinamos reikšmės tipas turi būti tas pats kaip ir metodo tipas. Jeigu metodas turi void   grįžties (return ) tipą, tai po raktažodžio return   rašomas iš karto kabliataškis. Taigi  return  atlieka dvigubą paskirtį: ji kontroliuoja metodo užbaigimą ir grąžina metodo skaičiavimų eigoje gaunamą reikšmę.

switch   komanda

Senesnėse programavimo kalbose dažnai tekdavo rašyti ilgas if-else grandines. Toks pakartotinų  if-else  operatorių panaudojimo poreikis kaip taisyklė atsiranda formuojant meniu punktus. switch   komanda iš esmės palengvina ir praskaidrina programas pakeisdama daugelį if-else komandų vienu  switch  operatoriumi.

switch  komandoje galimos char  , byte  , short   ir int   tikrinimo išraiškos. Gauta reikšmė ieškoma tarp case  šakų, kurios eina po switch   komandos ir tos šakos, kuriose reikšmė randama yra vykdomos. Panaudokime switch  komandą:

 

int cmd; // tarkime vartotojas įveda komandą switch(cmd) i { case 1 : System.out.println("Menu Item 1"); break; case 2 : System.out.println("Menu Item 2"); break; default : System.out.println("Invalid Command"); }

Po case  stovinčios reikšmės turi būti to paties tipo kaip ir switch  išraiškos rezultatas. Galima viena speciali žymė default , kurios šaka bus vykdoma, jeigu switch  išraiškos reikšmė nebus rasta tarp likusių šakų.

Atkreipiame dėmesį į break   komandos panaudojimą. Jei break  šakoje nenaudojama, tai papuolus į tą šaką ji bus vykdoma ir toliau pereinama prie eilinės šakos tikrinimo. Kartais tokia vykdymo eiga pageidautina, kartais ne. break  panaudojimas nutraukia kitų šakų tikrinimą. break  galite naudoti arba nenaudoti kiekvienai šakai individualiai ir tokiu būdu grupuoti vykdomas šakas.

Išimtys (exceptions )

Java kalba buvo padaryta remiantis C/C++ kalbomis, nes jos turėjo Java atsiradimo metu plačiausią vartotojų ratą. Tačiau Java toli gražu nėra šių kalbų mišinys. Kalbos saugumas yra viena išskirtinių Java savybių. Java autoriai skelbė, kad tai yra C++ su išspręstomis saugumo problemomis ir daugiagijo programavimo galimybėmis.

Išimčių (exceptions ) apdorojimas yra tipinė programų dirbančių tinklo aplinkoje dalia. Tinklo vartotojai iš savo patirtie žino kaip dažnai ir neprognozuotai gali nutrūkti ryšys. Jūsų programa turi būti pasiruošusi išlikti gyvybinga ir tokiomis aplinkybėmis. Galime įsivaizduoti groteskinę programą, kuri po kiekvieno operatoriaus rašo tas pačias tinklo ryšio tikrinimo komandas. Tinklų programavimo pradžioje kažkas panašaus ir buvo daroma. Geras išimčių programavimas neįmanomas, jei kalboje nėra numatyta adekvačių priemonių. Java kalboje tokios programavimo priemonės yra.

Išimtims perduodamas valdymas, kai praginos metu sistema susiduria su kritine situaciją, kuri neleidžia toliau tęsti normalią programos eigą. Tipiniai pavyzdžiai yra dalyba iš nulio arba panaudojimas tuščios (null) nuorodos. Jei jūs savo programoje nenumatėte tokios situacijos apdorojimo, tai programos vykdymas bus sustabdytas. Priešingu atveju, kai parašėte specialų išimties atvejui kodą, kuris leidžia toliau tęsti programos vykdymą, programa tuo atveju išliks gyvybinga ir pratęs savo darbą. Net jei problema neturi sprendimo, galite parašyti išimties apdorojimo kodą skirtą išsaugoti tuo momentu sukauptą naudingą informaciją ir atlaisvinti užsakytus kompiuterio resursus.

Techniškai išimčių (exceptions ) apdorojimo mechanizmas realizuojamas panaudojant try  ir catch  komandas. Šios komandos nustato kodo bloką kuriam numatytas apdorojimas išimties atveju. Kodo bloką nurodote po try   pažymėdami jį kaip įprasta tarp riestinių skliaustų, o catch   nurodo kiekvienai generuotai išimčiai savą apdorojimo būdą. Ištirkime paprastą dalybos iš nulio problemą:

 

int i = 0; i = i / i;

Vykdydama šį kodą, Java pragina generuos išimtį (exception ). Programa bus pabaigta ir bus atspausdintas klaidos pranešimas ekrane. Už programą užmokėjęs jūsų klientas paskambins jums kaip tik tuo metu, kai sėdate už šventinių pietų stalo. Ar nebūtų geriau pasirūpinti, kad klientams būtų mažiau suteikiama pretekstų gadinti jums gyvenimą?  try  /  catch  mechanizmas ateina į pagalbą sprendžia tokio tipo problemas:

 

int i = 0; try { i = i / i; } catch (ArithmeticException e) { System.out.println("Dalyba iš nulio, toliau tęsiu darbą"); }

Po try   bloko galite nurodyti bet kokį catch   blokų skaičių. Po kiekvienos išimties praginos sistema sukuria klaidą aprašantį objektą. Šis klaidos aprašymo objektas praplečia Exception  klasę. Toliau yra perduodama programos vykdymo eiga išimčių apdorojimui. Jei nėra nei vieno išimties apdorotojo, programa sustabdoma. Savo programoje mes numatėme ArithmeticException išimties apdorojimą. Tačiau kitų išimčių atveju mūsų programos vykdymas sustotų.

Gavęs išimties generavimą, kompiuteris ieško tarp visų catch  blokų kurie galėtų ją apdoroti. Pirmiausiai ieškomas geriausiai sutampantis. Jeigu nerasta tiksliai sutampančio, tuomet keliaujama paveldėjimo medžiu, kad rasti artimiausią tinkamą. Kadangi aritmetinė išimtis (ArithmeticException ) yra Exception  poklasė, mūsų atveju ji ir bus pasirinkta. Šią koncepciją lengviau suprasti analizuojant pavyzdžius.

 

int i = 0; try { i = i / i; } catch (ArithmeticException e) { System.out.println("Dalyba iš nulio, toliau tęsiu darbą"); } catch (Exception e) { System.out.println("Turime tam tikrų problemų"); // Vykdome resursų atlaisvinimo operacijas ... // Atkuriame išimtis throw(e); }

Pateiktame kode galite pastebėti problemą. Mes galime gauti išimtį, bet nežinosime su kokia išimtimi turime reikalą. Jeigu nežinote kaip ją apdoroti, tai geriausia duoti tai padaryti praginos sistemai. Čia mes taip ir darome - pirma atlaisviname resursus, o toliau išimties apdorojimo darbą perduodame praginos sistemai.

throw  komanda perduoda objektą išimties apdorojimo grandinei. Galite turėti daugelio lygių  try  ir  catch  sistemą. throw  komanda ignoruoja einamąjį lygį ir ieško naujo tinkamo išimties apdorojimo. Jei tokio neatsiras, programa bus sustabdyta.

Kartais jums reikia įvykdyti kodo dalį net tuo atveju, kai buvo generuota išimtis. Tokiu atveju reikiamas vykdyto blokas patalpinamas po  finally  komandos. Nepriklausomai dėl ko  try  bloko vykdymas buvo baigtas (ar sėkmingai iki bloko galo, ar anksčiau pabaigtas dėl išimties, dėl valdymo su break   ar  continue),  finally  blokas visuomet bus vykdomas. try  , catch   ir  finally  skeletonas atrodo taip:

 

try { // bandyk atlikti kodą, kuriame gali pasitaikyti išimčių } finally { // atliekame bet kuriuo atveju reikalingas komandas } catch (ArithmeticException e) { // adorojame dalybos iš nulio išimtį }

Pateiktas programos skeletonas yra geras karkasas dirbant su kodo dalimi, kurioje gali būti generuotos išimtys (exceptions ). Toks kodo blokas apjungiamas try   komanda. Išimčių apdorojimas padaro jūsų programą žymiai gyvybingesne.

4-14 lentelėje bendras generuojamų praginos sistema išimčių sąrašas. Dauguma API klasių turi savas išimtis. Kai naudojate naują klasę, susipažinkite su išimtimis, kurias ji gali generuoti.

Išimtis (exception ) Aprašymas
ArithmeticException Išimtys atsirandančios atliekant aritmetinius veiksmus. Pavyzdžiui, dalyba iš nulio.
ArrayIndexOutOfBoundsException Jūs panaudojote indeksą, kurio reikšmė nepatenka į masyvo rėžius. Prisiminkite, kad masyvo elementai indeksuojami pradedant nuo 0 ir baigiant N-1, kur N yra masyvo ilgis.
ArrayStoreException Jūs bandote saugoti blogo tipo objektą masyve. Objektas turi būti arba to paties tipo, arba poklasė, arba objektas kuriame realizuojamas nurodytas interfeisas.
CastClassException Blogai panaudotas tipo apribojimo operatorius cast.
InstantiationException Jūs bandote inicijuoti interfeisą arba abstrakčią klasę.
NegativeArraySizeException Bandote sukurti neigiamo ilgio masyvą.
nullPointerException   Bandote panaudoti nuorodos kintamąjį, kuris nėra inicijuotas arba yra tuščias ( null ).
NumberFormatException Eilutės reikšmė negali būti konvertuota į skaičių.
OutOfMemoryError Netgi surinkus šiukšles, nepakanka atminties tolimesniam programos vykdymui. Naujiems kompiuteriams su dideliais resursais tai atsitinka retai, bet teoriškai taip gali būti.
SecurityException Bandote atlikti operacijas, kurios dėl saugumo apribojimų neleidžiamos atlikti.
StringIndexOutOfBoundsException Mėginant panaudoti eilutę kaip masyvą, jūs nurodėte indekso reikšmę, kuri nepatenka į eilutės masyvo rėžius.
4-14 lentelė. Praginos išimtys.

Toliau

Į šį skyrių galėsite visuomet atsigręžti, kai iškils sintaksės klausimai. Dabar subrendome linksmesniems dalykams - pasiaiškinti kaip veikia įskiepiai. Kitame skyriuje išmoksime kurti interaktyvius įskiepius, kurie galės papuošti jūsų Interneto puslapius.

Atgal       Kitas Skyrius