Zbir ispravnih
Učitava se n, pa n reči. Neke su celi brojevi, a neke nisu. Ispisati zbir svih reči koje su celi brojevi i, u drugom redu, broj neispravnih.
Primer
Ulaz
6
12 abc 5 -3 7x 100Izlaz
114
2Izuzetak (exception) je greška koja nastaje dok program radi: deljenje nulom, pogrešan unos, pristup nepostojećem elementu niza, nepostojeća datoteka. Ako se izuzetak ne obradi, program se prekida. Ovde je objašnjeno kako se izuzeci hvataju, kako se sami prijavljuju i kako se pravi sopstveni izuzetak.
Sledeći program pada već u drugom redu metode main, a poslednja naredba se nikada ne izvrši:
public class Main {
public static void main(String[] args) {
int[] niz = {10, 20, 30};
System.out.println(niz[3]); // indeks 3 ne postoji
System.out.println("Kraj programa");
}
}
Na ekranu se pojavljuje poruka sa imenom izuzetka i redom u kome je nastao:
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: Index 3 out of bounds for length 3
at Main.main(Main.java:4)
Ovaj ispis (stack trace) je najkorisnija informacija pri traženju greške: kaže šta se desilo i gde.
| Izuzetak | Kada nastaje |
|---|---|
ArithmeticException | celobrojno deljenje nulom |
ArrayIndexOutOfBoundsException | indeks niza van opsega |
NullPointerException | poziv metode preko reference koja je null |
NumberFormatException | Integer.parseInt("12a") |
InputMismatchException | Scanner očekuje broj, a unet je tekst |
FileNotFoundException | datoteka ne postoji |
Kod koji može da izazove izuzetak stavlja se u blok try. Ako izuzetak nastane, izvršavanje se prebacuje u odgovarajući blok catch, a program nastavlja dalje.
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String[] unosi = {sc.next(), sc.next(), sc.next()};
for (String s : unosi) {
try {
int broj = Integer.parseInt(s); // može baciti NumberFormatException
int rezultat = 100 / broj; // može baciti ArithmeticException
System.out.println("100 / " + broj + " = " + rezultat);
} catch (NumberFormatException e) {
System.out.println("'" + s + "' nije ceo broj");
} catch (ArithmeticException e) {
System.out.println("Deljenje nulom: " + e.getMessage());
}
}
System.out.println("Program je zavrsen normalno.");
}
}
Blokova catch može biti više; proveravaju se redom. Više vrsta izuzetaka može se uhvatiti i jednim blokom: catch (NumberFormatException | ArithmeticException e).
Česta primena: program traži broj sve dok korisnik ne unese ispravnu vrednost.
import java.util.Scanner;
public class Main {
static int ucitajOcenu(Scanner sc) {
while (true) {
System.out.print("Ocena (1-5): ");
String s = sc.next();
try {
int x = Integer.parseInt(s);
if (x >= 1 && x <= 5)
return x;
System.out.println("Ocena mora biti od 1 do 5.");
} catch (NumberFormatException e) {
System.out.println("To nije broj.");
}
}
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int ocena = ucitajOcenu(sc);
System.out.println("Uneta ocena: " + ocena);
}
}
Blok finally se izvršava uvek – i kada je izuzetak nastao i kada nije. Koristi se za oslobađanje resursa (zatvaranje datoteke, veze sa bazom).
public class Main {
static int podeli(int a, int b) {
try {
return a / b;
} catch (ArithmeticException e) {
System.out.println("greska: deljenje nulom");
return 0;
} finally {
System.out.println("finally za " + a + "/" + b); // izvršava se i posle return
}
}
public static void main(String[] args) {
System.out.println(podeli(10, 2));
System.out.println(podeli(10, 0));
}
}
Za resurse je kraći oblik try-with-resources: objekat napravljen u zagradi posle try automatski se zatvara na kraju bloka.
import java.io.FileWriter;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
public class Main {
public static void main(String[] args) {
// FileWriter se sam zatvara na kraju bloka try
try (FileWriter f = new FileWriter("rezultat.txt")) {
f.write("Prvi red\n");
f.write("Drugi red\n");
} catch (IOException e) {
System.out.println("Greska pri pisanju: " + e.getMessage());
}
try {
for (String red : Files.readAllLines(Path.of("rezultat.txt")))
System.out.println("> " + red);
Files.readAllLines(Path.of("nepostojeca.txt"));
} catch (IOException e) {
System.out.println("Ne mogu da procitam: " + e.getMessage());
}
}
}
Metoda može sama da prijavi grešku naredbom throw. Tako se, na primer, sprečava da objekat dobije nedozvoljeno stanje:
public class Main {
static class Racun {
private double stanje;
void uplati(double iznos) {
if (iznos <= 0)
throw new IllegalArgumentException("Iznos mora biti pozitivan");
stanje += iznos;
}
void isplati(double iznos) {
if (iznos > stanje)
throw new IllegalStateException("Nema dovoljno novca (stanje " + stanje + ")");
stanje -= iznos;
}
}
public static void main(String[] args) {
Racun r = new Racun();
r.uplati(1000);
try {
r.isplati(300);
r.isplati(900);
System.out.println("Ovo se ne ispisuje");
} catch (IllegalStateException e) {
System.out.println("Odbijeno: " + e.getMessage());
}
try {
r.uplati(-50);
} catch (IllegalArgumentException e) {
System.out.println("Odbijeno: " + e.getMessage());
}
}
}
Java razlikuje dve vrste izuzetaka:
RuntimeException) – greške u programu, kao NullPointerException; ne moraju se hvatati;IOException) – očekivane spoljne greške; prevodilac zahteva da se uhvate ili da metoda u zaglavlju navede throws IOException.public class Main {
// sopstveni izuzetak: nasleđuje Exception (proveren izuzetak)
static class NeispravanJmbgException extends Exception {
private static final long serialVersionUID = 1L; // oznaka verzije (preporuka za klase izuzetaka)
NeispravanJmbgException(String poruka) {
super(poruka);
}
}
// throws: metoda najavljuje da može baciti ovaj izuzetak
static void proveri(String jmbg) throws NeispravanJmbgException {
if (jmbg.length() != 13)
throw new NeispravanJmbgException("JMBG mora imati 13 cifara, a ima " + jmbg.length());
for (char c : jmbg.toCharArray())
if (!Character.isDigit(c))
throw new NeispravanJmbgException("JMBG sadrzi znak koji nije cifra: " + c);
}
public static void main(String[] args) {
String[] primeri = {"0101010710001", "12345", "01010107A0001"};
for (String j : primeri) {
try {
proveri(j);
System.out.println(j + ": ispravan oblik");
} catch (NeispravanJmbgException e) {
System.out.println(j + ": " + e.getMessage());
}
}
}
}
Za svaki zadatak postoji primer, uputstvo i rešenje. Rešenja su provereno tačna na primerima iz teksta.
Učitava se n, pa n reči. Neke su celi brojevi, a neke nisu. Ispisati zbir svih reči koje su celi brojevi i, u drugom redu, broj neispravnih.
6
12 abc 5 -3 7x 100114
2Svaki red ulaza ima oblik a op b, gde je op jedan od + - * /. Za svaki red ispisati rezultat celobrojne operacije ili poruku: GRESKA: deljenje nulom, GRESKA: nije broj ili GRESKA: nepoznata operacija. Prvi red sadrži broj izraza n.
5
7 + 5
9 / 0
8 * x
20 / 3
4 ^ 212
GRESKA: deljenje nulom
GRESKA: nije broj
6
GRESKA: nepoznata operacijacatch (Exception e) { } – greška se tada „proguta“ i teško se pronalazi.catch: specifičniji izuzetak pre opštijeg (npr. NumberFormatException pre IllegalArgumentException), inače program neće da se prevede.if (b != 0), uradi to.1. Šta se dešava sa izuzetkom koji niko ne uhvati?
2. Kada se izvršava blok finally?
3. Koji izuzetak baca Integer.parseInt("12a")?
4. Čemu služi reč throws u zaglavlju metode?