U programiranju, pojam “parser” se odnosi na softversku komponentu koji vrši analizu struktura podataka kako bi ih preoblikovao ili izvukao određene informacije.
Ugrađeni parseri u Javi koji prevode string u proste tipove su:
Scanner
klasa u programskom jeziku Java omogućava jednostavan unos podataka sa standardnog ulaza ili iz drugih izvora podataka, kao što su datoteke. Ova klasa se nalazi u paketu java.util
i pruža različite metode za čitanje različitih tipova podataka, poput celih brojeva, decimalnih brojeva, nizova karaktera itd.
Evo nekoliko ključnih pojmova i primera korišćenja Scanner
klase:
Inicijalizacija objekta Scanner:
import java.util.Scanner;
Scanner unos = new Scanner(System.in);
Ova linija koda kreira novi objekat klase Scanner
koji će čitati podatke sa standardnog ulaza (System.in
).
Čitanje celih brojeva:
System.out.print("Unesite ceo broj: ");
int broj = unos.nextInt();
System.out.println("Uneli ste: " + broj);
Metoda nextInt()
se koristi za čitanje celih brojeva sa standardnog ulaza.
Čitanje decimalnih brojeva:
System.out.print("Unesite decimalni broj: ");
double decimalniBroj = unos.nextDouble();
System.out.println("Uneli ste: " + decimalniBroj);
Metoda nextDouble()
omogućava čitanje decimalnih brojeva.
Čitanje nizova karaktera:
System.out.print("Unesite tekst: ");
String tekst = unos.next();
System.out.println("Uneli ste: " + tekst);
Metoda next()
čita niz karaktera do prvog razmaka ili nove linije.
Zatvaranje Scanner objekta:
unos.close();
Kada završite s radom sa Scanner
objektom, preporučljivo je zatvoriti ga kako bi se oslobodili resursi.
Na sledećem linku možete videti sve metode klase Scanner
.
Uz to, Scanner
klasa se može koristiti i za čitanje podataka iz datoteka pomoću konstruktora koji prima File
objekat.
import java.io.File;
Scanner fileScanner = new Scanner(new File("putanja/do/datoteke.txt"));
// Rad sa Scanner objektom za čitanje datoteke
Ovde je postavljen Scanner
objekat da čita podatke iz datoteke “putanja/do/datoteke.txt”. Treba voditi računa o obradi izuzetaka, naročito kada radimo sa datotekama koje možda ne postoje.
Napisati jednostavan program u Javi koji sa standardnog ulaza čita dva realna broja i ispisuje njihov količnik.
U kojim slučajevima program, koji predstavlja rešenje zadatka 1
, neće raditi i zašto?
Pri pozivu nekog metoda, moguće je da dođe do različith vrsta neregularnih stanja.
Jedan način rukovanja takvim (izuzetnim) situacijama jeste proveravanje svih kritičnih uslova pre navodjenja dela koda koji može biti ‘ugrožen’ neproverenim greškama. Mana ovakvog rada jeste nečitak kod u kome se mešaju provera uslova za regularan tok programa i obrada u slučaju neispunjenosti uslova ikod koji se izvršava pri regularnom radu.
Da bi obezbedili razdvajanje koda koji se izvršava kada program teče glatko od obrade ‘neregularne’ situacije objektni jezici uvode:
U Java programiranju, “izuzetak” (eng. exception) je događaj koji narušava normalan tok izvođenja programa. Kada dođe do izuzetka, Java generiše objekat koji predstavlja tu iznimku. Taj objekat sadrži informacije o tome šta je pošlo po zlu, uključujući i trag steka (stack trace), koji pokazuje gde se izuzetak dogodio.
Izuzeci u Javi se koriste kako bi se nosili sa neočekivanim situacijama ili greškama tokom izvođenja programa. To može uključivati situacije poput deljenja sa nulom, pristupa nepostojećem elementu niza ili bilo koje druge situacije koje bi mogle dovesti do problema tokom izvođenja programa.
Primer koda koji baca i hvata izuzetak u Javi može izgledati ovako:
public class PrimerIzuzetka {
public static void main(String[] args) {
try {
// Blok koda u kojem može doći do izuzetka
int a = 10;
int b = 0;
System.out.println(a / b);
} catch (ArithmeticException e) {
// Blok koda koji se izvršava ako dođe do izuzetka
System.out.println("Došlo je do aritmetičke greške: " + e.getMessage());
}
}
}
U ovom primeru, JVM će prvo pokušati da podeli dva broja. Pošto deljenje nulom nije moguće, biće bačen izuzetak tipa ArithmeticException
. Taj izuzetak će biti uhvaćen u catch delu i izvršiće se kod koji se tu nalazi.
throw
je ključna reč koja se koristi za ručno izazivanje (bacanje) izuzetka. Kada se throw
koristi u programskom kodu, označava trenutnu tačku gde se programski izvršavanje zaustavlja i prenosi kontrolu do bloka koda koji je zadužen za hvatanje (catch) tog izuzetka.
Koristi se u sledećem kontekstu:
public class PrimerBacanjaIzuzetka {
public static void main(String[] args) {
try {
// Izazivanje izuzetka
throw new IllegalArgumentException("Ovo je poruka izuzetka");
} catch (IllegalArgumentException e) {
// Hvatanje i obrada izuzetka
System.out.println("Uhvaćen izuzetak: " + e.getMessage());
}
}
}
U ovom primeru, throw
se koristi za izazivanje izuzetka tipa IllegalArgumentException
sa odgovarajućom porukom. Zatim se izuzetak hvata i obrađuje u bloku catch
, gde se ispisuje poruka izuzetka. Nakon throw
je neophodno proslediti objekat. Objekat kojim se opisuje greška ne može pripadati proizvoljnoj klasi. Klasa kojoj objekat pripada mora da se nađe u lancu nasleđivanja klase Throwable
, jer sam Javin kompajler vrši proveru tipa objekta pri prevođenju throw komande.
Korišćenje throw
je posebno korisno kada programer želi signalizirati da se desila određena greška ili neispravno stanje koje zahteva specifičnu reakciju. Ovo može uključivati proveru unosa korisnika, rukovanje s resursima, ili bilo koje druge situacije gde je potrebno obavestiti sistem o nečemu neočekivanom. Važno je odabrati odgovarajući tip izuzetka koji najbolje opisuje prirodu problema.
Za skoro sve izuzetke koji su obuhvaćeni podklasama klase Exception potrebno je uključiti kod za njihovu obradu ili program neće proći kompajliranje, tj. prevodilac NE DOZVOLJAVA njihovo ignorisanje.
RunTimeException (nasleđuje klasu Exception
) izuzeci se tretiraju drugačije, jer se u njih najčešće svrstavaju izuzeci koji se pojavljuju kao
posledica ozbiljnijih grešaka u kodu, čija obrada ne bi mogla ništa značajno promenila. Prevodilac dozvoljava njihovo ignorisanje.
Neke podklase klase RuntimeException
:
ArithmeticException
: neispravan rezultat aritmetičke operacije poput deljenja nulom.IndexOutOfBoundsException
: indeks koji je izvan dozvoljenih granica za objekat poput niza, stringa ili vektora.NegativeArraySizeException
: upotreba negativnog indeksa niza.NullPointerException
: poziv metoda ili pristup podatku članu null objekta.ArrayStoreException
: pokušaj dodeljivana reference pogrešnog tipa elementu niza.ClassCastException
: pokušaj kastovanja objekta neodgovarajućeg tipa.Na osnovu toga da li prevodilac insistira njihovom proveravanju ili ne, izuzeci se dele u dve grupe:
proveravani izuzeci (checked)
Exception
i svi koji nisu u lancu RuntimeException klase
.
Ako metoda baca neki proveravani izuzetak, poziv te metode mora da bude uokviren try/catch blokom koji
hvata taj izuzetak, a metoda mora da bude označena ključnom reči throws
i nazivom klase izuzetka koji
baca.public class Test {
static void exceptionInMethod() throws Exception {
throw new Exception("Exception");
}
// posto se Exception hvata unutar main metoda, main metod ne mora biti oznacen kljucnom reci throws
public static void main(String[] args) {
try {
exceptionInMethod();
}
catch(Exception ex) {
System.out.println(ex.getMessage());
}
}
}
neproveravani izuzeci (unchecked)
Oni koji su izvedeni iz RuntimeException
. Klase koje su navedene u tabeli Javinih predefinisanih izuzetaka, uglavnom,
nasleđuju klasu RuntimeException pa pripadaju grupi neproveravanih izuzetaka.
Ako metoda baca neki neproveravani izuzetak, poziv te metode može, ali ne mora biti uokviren try/catch
blokom koji hvata taj izuzetak.U delu try/catch bloka
catch (ExceptionType1 identifier) {
// …
}
kod koji obrađuje izuzetak se poziva za ExceptionType1 ili bilo koju njegovu podklasu
.
Ako je u nekom try/catch bloku navedeno nekoliko catch blokova sa nekoliko tipova izuzetaka u istoj klasnoj hijearhiji, potrebno je blokove postaviti tako da se prvo hvata izuzetak najniže podklase, pa redom prema najvišoj superklasi.
// neispravna sekvenca catch blokova
// neće se prevesti
try {
// try block code
} catch(Exception e){ ... }
catch(ArithmeticException e) { ...
// ispravna sekvenca catch blokova
try {
// try block code
} catch(ArithmeticException e){ ... }
catch(Exception e) { ...
Pretpostavimo da se u main() metodu u nekom trenutku poziva metod a() u kome se poziva metod b(), a u njemu metod c().
c() {
}
b() {
c();
}
a() {
b();
}
main() {
a();
}
O čitavom lancu pozivanja i o tome koji je metod dokle stigao sa izvršavanjem vodi računa JVM. Struktura u kojoj beleži lanac pozivanja se naziva call stack. Zahvaljujući call stack-u JVM zna koja je prva naredna komanda koja treba da bude izvršena nakon regularnog završetka nekog pozvanog metoda ili kome treba da prosledi generisani izuzetak u slučaju neregularnog završetka pozvanog metoda. Ako JVM ne uspe ni u jednom metodu na call stack-u da pronađe obradu izuzetka program prekida rad.
Klasa Throwable
` je bazna klasa za sve Java izuzetke i ima:
public class Test {
static void b() throws Exception {
throw new Exception("Poruka");
}
static void a() throws Exception {
try {
a();
}
catch(Exception ex) {
ex.printStackTrace();
/**
* b
* a
* main
*/
ex.fillInStackTrace();
throw ex;
}
}
public static void main(String[] args) {
try {
a();
}
catch(Exception ex) {
ex.printStackTrace();
/**
* a
* main
*/
}
}
}
Dva osnovna razloga:
Primer:
// exception class – minimalna definicija
public class DreadfulProblemException extends Exception
{
// Konstruktori
public DreadfulProblemException(){ } // Default constructor
public DreadfulProblemException(String s) {
super(s); // Call the base class constructor
}
}
Šta još dodati?
Koristi se za pospremanje (clean-up) tj. oslobađanje resursa (npr. zatvaranje fajla). Asociran je sa određenim try blokom (kao i catch blokom) i izvršava se uvek nakon što se završi izvršavanje try i catch bloka. Može se koristiti i s try blokom koji sadrži kod koji ne baca nikakav izuzetak:
Iskoristite try/catch blokove kako bi uhvatili izuzetke koji se mogu pojaviti u zadatku 1
i obradite ih (ispišite neku poruku).
Uradite zadatak 2
samo što će se vrednosti čitati iz fajla umesto sa standardnog ulaza.
Kreirajte izuzetak BrojeviSuJednaki. Ukoliko je apsolutna vrednost razlike brojeva, koji se čitaju iz fajlu u zadatku 2
, manja od 0.0001 potrebno je baciti izuzetak BrojeviSuJednaki i obraditi ga.