Top 10 įžvalgų apie Java OCA sertifikavimą

2019 04 17

Baltic Amadeus mes nuolat siekiame būti geriausiais savo srities ekspertais. Profesionalumas ir nuolatinis mokymasis ne be reikalo yra dvi iš mūsų pagrindinių vertybių. Savo tobulėjimą žymime išsilaikydami vis naujus ir vertingus sertifikatus. Oracle Certified Professional sertifikatai Java programuotojams yra viena iš viršukalnių, į kurią norisi įkopti. Visgi, tai nėra pati lengviausia užduotis – egzaminas sudarytas iš daugybės suktų klausimų, reikalaujančių kelioms valandoms tapti tikrų tikriausiu kompiliatoriumi. Šiame įraše pasidalinsiu 10 Java gudrybių, kurias jau spėjote pamiršti arba niekada nebuvote su jomis susidūrę.

Numatytos reikšmės

Pradėkime nuo šio to lengvesnio, tačiau primiršto – numatytų kintamųjų reikšmių. Java programavimo kalboje pirminiai kintamieji turi numatytas reikšmes tokias, kaip int reikšmė 0, boolean – false ir t.t.

public class DefaultValues {
private int x;
@Test
public void defaultValues() {
int y = 10;
assert(10, x+y);
}
}

Šis testas susikompiliuos ir bus priimtas, nes x yra int, kurio numatyta reikšmė – 0. Ką darysime, jeigu x yra ne klasės, o lokalus kintamasis?
public void defaultValues() {
int y = 10;
int x;
assertEquals(10, y + x);
}

Šis kodas nesusikompiliuos, nes lokalūs kintamieji turi būti inicijuojami prieš tai, kai su jais atliekame bet kokius veiksmus, nekreipiant dėmesio į numatytas reikšmes. Būkite atidūs, nes tai gali būti viena iš priežasčių, kodėl kode lieka daug klaidų, nors šiuolaikiniai IDE ir gelbėja mus, parodydami kompiliavimo klaidas.

Pavadinimai

Dabar, nerkime į nepažintas kintamųjų užvadinimo gelmes. Kuris iš apačioje pateiktų variantų yra validus?
String A$B;
String _helloWorld;
String 1980_s;
String true;

Mes, java programuotojai, esame pratę prie gerųjų praktikų, suteikiant vardus įvairiems java komponentams, todėl atrodytų, kad visi aukščiau išvardyti kintamieji neturėtų būti priimti kompiliatoriaus. Įdomiausia tai, kad java priima pusę iš jų.

A$B yra tinkamas vardas (vardams kurti gali būti naudojami įvairūs simboliai, tarp jų ir „$“).
Taip pat, vardas gali prasidėti „_“. Vardas negali prasidėti skaičiumi, taigi 1980_s yra netinkamas variantas ir kompiliatorius jo nesupras. Java kalba taip pat turi keletą raktažodžių (pvz. class, if, new ir true), kurių negalima naudoti pavadinimuose, taigi 4 eilutė yra neteisinga.

Skaičiai

Java programavimo kalboje, skaičiai gali turėti įvairias formas. Tai net tik skaičiai nuo 0 iki 9, bet ir raidės bei simboliai. Aptarkime keletą pavyzdžių.
int A = 1_234_000;
double B = 1_234_.0;
double C = 1_234.0; double D = 1_234.0;
double E = 1_234.0;

Simbolis „_“ gali būti naudojamas atskirti logines skaičių dalis, pavyzdžiui, tūkstančius. Tai vienintelis atvejis, kur turėtų būti naudojamas apatinis brūkšnys. Yra keletas taisyklių, kurių būtina laikytis: taškas ir apatinis brūkšnys yra netinkama kompanija vienas kitam ir apatinis brūkšnys negali atsirasti skaičiaus pradžioje arba pabaigoje. Pagal šias taisykles, tik A ir E susikompiliuos, kiti – ne.

Antrajame pavyzdyje matote raides, naudojamas skaičiams:
int A = 9L;
int B = 0b101;
int C = 0xE;
double D = 0xE;

A variantas yra netinkamas, nes „L“ arba „l“ nurodo long skaičiaus formatą, taigi jis negali būti priskirtas prie int.
B variantas yra geras – „0b“ nurodo dvejetainius skaičius nuo Java 7 išleidimo. B = 5.
C ir D taip pat yra teisingi – „0x“ yra šešioliktainių skaičių pradžia, taigi C = 14, D = 14.0.

Didžiausios skaičių reikšmės

Būkite atsargūs turėdami reikalų su didžiausiais sveikais skaičiais arba ilgomis reikšmėmis.
System.out.println(Integer.MAX_VALUE);

Didžiausia sveikojo skaičiaus reikšmė yra 2147483647. Kas būtų, jeigu padidintume jį vienetu?
System.out.println(Integer.MAX_VALUE+1);

Nepamirškim, kad sveikasis skaičius gali būti ir neigiamas. Rezultatas yra -2147483648. Kas būtų, jeigu jį padidintume?
System.out.println(Integer.MAX_VALUE+2);

Reikšmė išlieka neigiama, bet nuspėjama: -2147483647.
Tas pats taikoma ir ilgoms reikšmėms:

System.out.println(Long.MAX_VALUE); // 9223372036854775807
System.out.println(Long.MAX_VALUE+1); // -9223372036854775808

Srauto kontrolė

Tikriausiai, neapsiriksiu pasakęs, kad nedažnai sutinkate tokį kodą:
FIRST_LOOP: for (int a = 1; a <= 4; a++) {
for (char x = ‘a’; x <= ‘c’; x++) {
if (a == 2 || x == ‘b’)
continue FIRST_LOOP;
System.out.print(“ “ + a + x);
}
}

Iš tikrųjų, etiketės (labels) gali būti priskirtos skirtingoms java kodo dalims. Jos suteikia galimybę, pvz., išeiti iš išorinio ciklo. Bet tas naudojama nedažnai – goto šiais laikais laikoma bloga praktika.
Šio kodo rezultatas yra ‘ 1a 3a 4a’.

Eilučių lygybė

Sena, bet pamiršta tema, taigi pasikartokime.
Lygu ar ne?
String x = new String(„Hello World“);
String y = „Hello World“;
System.out.println(x == y);

Na, ne. Kai == lygina objektus ir new String sukuria naują eilutę, o „some string“ atneša eilutę iš jų pool‘o.

Štai kitas pavyzdys:
String x = „Hello World“;
String y = „Hello World“;
System.out.println(x == y);

Abi eilutės yra paimtos iš pool’o, tokiu būdu jos nurodo į ta pačią vietą atmintyje ir yra visiškai lygios.

Dvejatainė paieška

Dar viena retai naudojama java funkcija yra dvejetainė paieška. Tai greitas būdas vykdyti paiešką masyve.
int[] numbers = {2,4,6,8};
System.out.println(Arrays.binarySearch(numbers, 2)); // 0
System.out.println(Arrays.binarySearch(numbers, 4)); // 1
System.out.println(Arrays.binarySearch(numbers, 1)); // -1
System.out.println(Arrays.binarySearch(numbers, 3)); // -2
System.out.println(Arrays.binarySearch(numbers, 9)); // -5

Turint sveikųjų skaičių masyvą, Arrays.binarySearch leidžia mums surasti int poziciją jame.

Taip skaičius 2 yra randamas 0 pozicijoje, o skaičius 4 – 1 pozicijoje.
Kai ieškome reikšmių ne masyve, rezultatas yra skaičiuojamas pagal formulę – pozicija, kur skaičius turi būti įterptas minus 1. Kai 1 yra įterpiamas į poziciją 0, paieškos rezultatas yra -1. Pritaikant šią taisyklę 3 ir 9, gauname -2 ir -5.

Visgi, yra vienas nedidelis apribojimas – masyvas turi būti surūšiuotas. Kompiliuojant nebus klaidų ar išimčių, bet dvejetainė paieška tampa neaiški:
int[] numbers2 = {3,2,1};
System.out.println(Arrays.binarySearch(numbers2, 2)); // 1
System.out.println(Arrays.binarySearch(numbers2, 3)); // -4

Kai 2 yra randamas pozicijoje 1, skaičius 3 kažkodėl atsiduria -4 pozicijoje, kai tikėtinas rezultatas yra 0. Neapsigaukite ir tokią paiešką naudokite apdairiai.

Masyvas ir sąrašas

Masyvai ir sąrašai, iš pirmo žvilgsnio, gali atrodyti labai panašūs, visgi skirtumų jie turi. Aptarkime į pavyzdį:
String[] array = { „baltic“, „amadeus“ };
List list = Arrays.asList(array);
list.set(1, „IT“);
array[0] = „enjoy“;
for (String b : array) System.out.print(b + “ „);

Pirmiausiai, masyvas turi dvi eilutes „baltic“ ir „amadeus“. Tada iš šio masyvo sukuriamas sąrašas, naudojant Arrays klasės metodą asList. Antroji sąrašo vertė yra nustatyta kaip „IT“. Galiausiai, mes vėl grįžtame prie masyvo, kurio pirmoji reikšmė pakeičiama į „enjoy“.

Tuomet masyvo turinys yra atspausdinamas. Koks šio kodo rezultatas?

Atrodo lyg paprastas ir nesudėtingas atvejis, tačiau neapsigaukite ir neskubėkite, yra mažas „bet“. Kai iš masyvo kuriame sąrašus, jie dalijasi ta pačia vieta atmintyje su originaliu masyvu, tai reiškia, kad jie dalijasi ir ta pačia reikšme. Keičiant vieną, pasikeičia ir kitas. Turint tai omenyje, mūsų output‘as yra „enjoy IT“.

Šiuo atveju, sąrašas gauna ir keletą kitų masyvo ypatybių – nustatytą dydį. Taigi, add arba remove sąrašo sąsajos metodai parodys klaidą: UnsupportedOperationException.

Datos

Kuris iš apačioje esančių variantų yra 2019-03-07?
System.out.println(LocalDate.of(2019, 3, 7));
System.out.println(LocalDate.of(2019, 4, 7));
System.out.println(LocalDate.of(2019, Calendar.MARCH, 7));
System.out.println(LocalDate.of(2019, Month.MARCH, 7));

Pirmasis ir ketvirtasis variantai yra teisingi. Tai, ką matome, yra Java 8 LocalDate ir tradicinės Date mišinys. LocalDate pradeda skaičiuoti mėnesius nuo 1, kai Date naudoja Calendar, kuris indeksuoja mėnesius pradedant nuo 0. Taigi, Calendar.MARCH = 2 ir LocalDate.of(2019,2,7) yra vasario 7.

Local Date, taip pat, turi keletą naudingų metodų datos manipuliacijai, pavyzdžiui, plusDays (prideda dienų skaičių datoje, netgi didinant mėnesį/metus, jei būtina). Visgi, kodas apačioje yra klaidingas, nes šie principai neveikia, kuriant objektus. Būkite tikslūs.
LocalDate date = LocalDate.of(2019, Month.FEBRUARY, 30);
// java.time.DateTimeException: Invalid date ‘FEBRUARY 30’

Numatyti metodai

Java 8 turi daug įdomių funkcijų, viena iš jų – numatyti metodai sąsajoms. Naudingi ar ne, jie gali tapti sąmyšio jūsų kode priežastimi. Sakykime, turime dvi sąsajas su tuo pačiu numatytu metodu

public interface JuniorProgrammer {
default int getBugsPerSecond() {
return 10;
}
}
public interface SeniorProgrammer {
default int getBugsPerSecond() {
return 10;
}
}

Sakytume, nedidelė problema, kai abu programuotojai padaro 10 bug’ų per sekundę, sąsajos gali būti naudojamos pakaitomis. Bet kas atsitinka, jeigu klasė implementuoja jas abi?
public class Programmer implements JuniorProgrammer, SeniorProgrammer {
}

Na, kompiliatorius to neleis. Klasė gali implementuoti kelias sąsajas, bet tuomet tos sąsajos negali turėti numatytųjų metodų su vienodais aprašais. Nebent numatytas metodas yra perrašomas:
public class Programmer implements JuniorProgrammer, SeniorProgrammer {
public int getBugsPerSecond() {
return 10;
}
}

Kompiliacija sėkminga, bet numatyti sąsajų metodai yra ignoruojami, taigi, šiuo atveju, jie beprasmiai.

OCA gali būti grėsminga patirtis. Šis straipsnis suteikia šiek tiek aiškumo aiškinantis sudėtingiausius java programavimo kalbos elementus, su kuriais galite susidurti savo egzamino metu arba tiesiog buvote primiršę rašydami idealų kodą su IDE pagalba.

Tiems, kuriems įdomu, rekomenduoju puikią Jeanne Boyarsky knygą „OCA: Oracle Certified Associate Java SE 8 Programmer I Study Guide: Exam 1Z0-808“. Tai ne tik puiki medžiaga ruošiantis egzaminui, bet puikiai tinka ir norint atšviežinti java žinias.

Kodą, naudojamą šio įrašo pavyzdžiams, galite rasti mano github puslapyje: https://github.com/keizik/java-tricks