w8_java.pdf

(281 KB) Pobierz
w8_java
Schemat obsługi wyj ą tków
JAVA - Wyj ą tki i strumienie
• wyjątek powstaje na skutek jakiegoś nieoczekiwanego
błędu
• wyjątek jest zgłaszany
• wyjątek jest obsługiwany
int a,b,c; String s;
try {
Beata Pańczyk - Java (Wykład 8)
//w bloku try umieszcza się instrukcje,
//które mogą spowodować wyjątek
a=b/c; //jeŜeli c=0 zostanie zgłoszony
//wyjątek AritmeticException
s=Integer.toString(a);
}
catch (AritmeticException e) {
//wyjatek jest obsługiwany w bloku catch
s="*"; }
2
Klasy wyj ą tków
Wyj ą tki kontrolowane i
niekontrolowane
• pochodne od klas RuntimeException i Error - wyjątki
niekontrolowane
• pozostałe wyjątki - kontrolowane , tzn.:
– metody zgłaszające te wyjątki wymieniają je jawnie w swojej
deklaracji w klauzuli throws
– metody te mogą zgłaszać tylko wymienione w klauzuli throws
wyjątki lub wyjątki ich podklas
– odwołania do tych metod wymagają jawnej obsługi ewentualnie
zgłaszanych wyjątków:
• poprzez konstrukcję try-catch lub
• poprzez wymienienie wyjątku w klauzuli throws
naszej metody (przesunięcie obsługi wyjątku do
miejsca wywołania naszej metody)
• wyjątki są obiektami klas wyjątków
• kaŜda nazwa wyjątku - to nazwa klasy
• w hierarchii dziedziczenia - klasa bazowa Throwable
• błędy fatalne (fatal error) są wyprowadzane z podklasy
Error klasy Throwable
• pozostałe błędy - podklasy klasy Exception
w przypadku operacji na liczbach rzeczywistych przy
dzieleniu przez 0 wyj ą tek nie jest zgłoszony a warto ść
wyniku jest postaci POSITIVE_INFINITY (lub
NEGATIVE_INFINITY), co po przekształceniu na
String da napis: " Infinity " (lub " -Infinity " )
3
4
Sekwencja działania
mechanizmu wyj ą tków
• wykonywane są kolejne instrukcje bloku try
• jeśli powstaje wyjątek - wykonanie bloku try jest przerywane
• sterowanie przekazywane jest do pierwszej w kolejności klauzuli
catch , której typ wyjątku pasuje do typu powstałego wyjątku
(naleŜy podawać najpierw te bardziej szczegółowe typy
wyjątków)
• inne klauzule catch nie są uruchamiane
• obsługująca wyjątek klauzula catch moŜe np. zmienić sekwencję
sterowania (poprzez return lub zgłoszenie nowego wyjątku za
pomocą instrukcji throw ). Jeśli nie zmienia sekwencji
sterowania, to wykonanie programu jest kontynuowane w
klauzuli finally (lub jeśli jej nie ma - od następnej instrukcji po
try - po ostatniej klauzuli bloku catch )
Klauzula finally
• słuŜy do wykonania kodu niezaleŜnie od tego czy wystąpił
wyjątek czy nie
• np.
boolean metoda(...) {
try { //instrukcje, które mogą spowodować wyjatek
}
catch (Exception e) { return false;
}
finally {
//uporządkowanie
5
}
return true;
}
• jeśli zaistniał wyjątek - uruchamiana jest klauzula catch, która
zwraca false na znak niepowodzenia i sterowanie przekazywane
jest do klauzuli finally; dopiero potem zwracany jest wynik - false
• jeśli nie było wyjątku - po zakończeniu instrukcji w bloku try
sterowanie od razu wchodzi do klauzuli finally
6
1
27932390.033.png 27932390.034.png 27932390.035.png 27932390.036.png 27932390.001.png 27932390.002.png
Własne wyj ą tki
Własne wyj ą tki
• wyjątki są obiektami klas pochodnych od Throwable,
aby stworzyć własny wyjątek naleŜy zdefiniować klasę
dziedziczącą podklasę Exception klasy Throwable,
np.:
class NowyWyjatek extends Exception {
...
Zgłaszanie wyjątku:
• jeśli nasza metoda ma zgłaszać wyjątek NowyWyjatek to
musi podać w deklaracji, Ŝe moŜe to zrobić tzn.:
void naszaMetoda ()throws nowyWyjatek
• naszaMetoda sprawdza warunki powstania błędu, jeśli
wystąpił błąd – tworzy wyjątek:
new NowyWyjatek(..)
i sygnalizuje go za pomocą instrukcji throw:
throw new NowyWyjatek(ew_param_konstr_z_info_o_bledzie)
}
w której moŜna zawrzeć pola i metody słuŜące
dodatkowej informacji o przyczynach powstania
wyjątku
7
8
Przykład - klasa wyj ą tku NiePoprawnyKod
i klasa komponentu PoleKodu
importjavax.swing.JTextField;
class NiePoprawnyKod extends Exception{ //klasawyjątku
public String info="Poprawnykodmapostać:nnnnn";
NiePoprawnyKod(String s){
info="Niepoprawnykod:"+s+"."+info;
Przykład – własne wyj ą tki c.d.
public String pobierzKod()throws NiePoprawnyKod{
final int N=6,P=2;
String kod=getText();
boolean poprawny=true;
char[]c=kod.toCharArray();
if (c.length!=N||c[P]!='')poprawny=false;
elsefor(int i=0;i<N;i++){
if (i==P)continue;
if (!Character.isDigit(c[i]))poprawny=false;
}
}
class PoleKodu extends JTextField {
//klasakomponentu
}
if (!poprawny)throw new NiePoprawnyKod(kod);
returnkod;
PoleKodu(){super();}
PoleKodu(String s){super(s);}
PoleKodu(int n){super(n);}
}
}
9
10
Przykład - wykorzystanie
własnego wyj ą tku
importjavax.swing.*;importjava.awt.*;importjava.awt.event.*;
public class Kodextends JFrame implements ActionListener {
PoleKodu pk=new PoleKodu(10);
JPanel glowny=new JPanel();JTextArea t=new JTextArea();
public Kod(){
setSize(320,150);
//setDefaultCloseOperation(EXIT_ON_CLOSE);
glowny.setLayout(new BoxLayout(glowny,BoxLayout.Y_AXIS));
JLabel l1=newJLabel("Wprowadźkod:",JLabel.CENTER);
JButton b=new JButton("Enter");b.addActionListener(this);
glowny.add(l1); glowny.add(pk);
glowny.add(b); glowny.add(t);
setContentPane(glowny);
setVisible(true);
Przykład - wykorzystanie
własnego wyj ą tku
public static void main(String[]args){new Kod();}
public void actionPerformed(ActionEvent e){
String tekst=null;
try {tekst=pk.pobierzKod();}
catch (NiePoprawnyKod ek){t.setText(ek.info);return;}
t.setText("Wprowadzonokod:"+tekst);
} }
}
11
12
2
27932390.003.png 27932390.004.png 27932390.005.png 27932390.006.png 27932390.007.png 27932390.008.png 27932390.009.png 27932390.010.png
Poj ę cie strumienia
Przodkowie hierarchii klas
strumieniowych
• programowanie operacji we/wy polega na uŜyciu
strumieni, które są obiektami klas strumieniowych z
pakietu java.io
strumie ń danych – pojęcie abstrakcyjne, oznacza ciąg
danych, do którego dane mogą być dodawane (operacja
zapisu do strumienia – strumie ń wyj ś ciowy ) i z którego
mogą być pobierane (operacja odczytu ze strumienia –
strumie ń wej ś ciowy )
• pobranie/zapis danych dotyczy określonych porcji danych
– w Javie są to strumienie bajtowe (atomem operacji jest
bajt) i strumienie znakowe (atomem jest znak Unicode - 2
bajty) – cztery hierarchie klas strumieniowych
Wejście
Wyjście
Strumienie
bajtowe
InputStream
OutputStream
Strumienie
znakowe
Reader
Writer
• są to klasy abstrakcyjne (nie moŜna tworzyć bezpośrednio
obiektów tych klas) – dostarczają metod m.in. do czytania
(read), zapisywania (write), zamykania strumieni (close)
13
14
InputStream, OutputStream
Reader, Writer
Podklasy InputStream
– AudioInputStream, ByteArrayInputStream,
FileInputStream, FilterInputStream,
ObjectInputStream, PipedInputStream,
SequenceInputStream,
StringBufferInputStream
Podklasy OutputStream :
– ByteArrayOutputStream, FileOutputStream,
FilterOutputStream, ObjectOutputStream,
PipedOutputStream
Podklasy Reader:
BufferedReader, CharArrayReader,
FilterReader, InputStreamReader,
PipedReader, StringReader
Podklasy Writer:
BufferedWriter, CharArrayWriter, FilterWriter,
OutputStreamWriter, PipedWriter, PrintWriter,
StringWriter
15
16
Zastosowanie strumieni danych
STRUMIENIE BAJTOWE
• utworzenie obiektu reprezentującego strumień (np.
obiektu klasy FileInputStream dla strumienia
we lub obiektu klasy BufferedWriter dla
strumienia wy)
• odczyt/zapis danych do/ze strumienia (np. metoda
read() dla obiektu FileInputStream lub metoda
write() dla obiektu BufferedWriter
• zamknięcie strumienia metodą close()
strumienie bajtowe - podklasy klas
abstrakcyjnych InputStream/OutputStream
FileInputStream/FileOutputStream - klasy
podrzędne, reprezentują strumienie bajtowe
powiązane z plikami
DataInputStream/DataOutputStream - klasy
reprezentujące filtrowane strumienie bajtowe
(umoŜliwiające odczyt danych typu int,float itp.)
strumienie plikowe - najczęstsze strumienie
bajtowe
17
18
3
27932390.011.png 27932390.012.png 27932390.013.png 27932390.014.png 27932390.015.png 27932390.016.png 27932390.017.png
Wej ś ciowe strumienie plikowe
• wejściowy strumień plikowy - obiekt FileInputStream(string)
z argumentem będącym nazwą pliku (moŜe być zgłoszony
wyjątek IOException )
read() - czyta 1 bajt z pliku (zwraca -1 gdy osiągnięto koniec
pliku)
• read(byte[], int1, int2) – odczytanie int2 bajtów ze strumienia do
tablicy i umieszczenie ich począwszy od elementu tablicy o
indeksie int1
• np.:
FileInputStream f=new FileInputStream("dane.txt");
int bajt=0;
while(bajt!=1){
bajt=f.read();
System.out.print(bajt+””);
Przykład - odczyt bajtów z pliku
importjava.io.*;
public class CzytajBajty {
public static void main(String[]args){
try { FileInputStream pl=new FileInputStream("D:/beata/java/dane.dat");
boolean eof=false;int ile=0;
while (!eof){
int input=pl.read();
System.out.print(input+"");
if (input==1)eof=true;else ile++;
}
pl.close();
System.out.print("\nWczytano"+ile+"bajtow.");
}catch(IOException e){System.out.println("Error "+e.toString());}
}
}
19
}
20
Wyj ś ciowe strumienie plikowe
Przykład - zapis bajtów do pliku
importjava.io.*;
public class ZapiszBajty {
public static void main(String[]args){
int []dane={ 71,73,70,56,57,97,15,0,15,0,128,0,0,
255,255,255,0,0,0,44,0,0,0,
0,15,0,15,0,0,2,33,132,127,161,200,
185,205,84,128,241,81,35,175,155,26,
228,254,105,33,102,121,165,201,145,169,
154,142,172,116,162,240,90,197,5,0,59};
• wyjściowy strumień plikowy - obiekt
FileOutputStream(string) z argumentem
będącym nazwą pliku (moŜe być zgłoszony
wyjątek IOException ); jeśli plik istnieje to jego
zawartość zostanie usunięta
FileOutputStream(string, true) – utworzenie
stumienia wy, który dopisuje dane do pliku
write() – zapisuje 1 bajt do pliku
write(byte[ ], int i, int n) – byte[] tablica bajtów
do zapisu, i – indeks pierwszego elementu do
zapisu, n – liczba bajtów do zapisu
try {
FileOutputStream pl=new FileOutputStream("obraz.gif");
for(int i=0;i<dane.length;i++)pl.write(dane[i]);
pl.close();
}
catch(IOException e){System.out.println("Error "+e.toString());}
}
21
}
22
Filtrowanie strumienia danych
Filtry bajtowe – strumienie
buforowane (strumie ń we)
Filtr - specyficzny typ strumienia, który
modyfikuje sposób, w jaki obsługiwany jest
bieŜący strumień danych
Wykorzystanie filtra:
• utworzenie strumienia powiązanego ze źródłem
danych lub miejscem ich zapisu
• utworzenie powiązania filtra ze strumieniem
• zapis/odczyt danych bezpośrednio z filtra a nie ze
strumienia
• filtry mogą być zagnieŜdŜane
Bufor – obszar przeznaczony do przechowywania danych
Buforowany strumie ń wej ś ciowy – wypełnia bufor
danymi, których program jeszcze nie wykorzystał
(program najpierw sprawdza bufor, zanim sięgnie do
źródła danych)
• BufferedInputStream(InputStream) – tworzy buforowany
strumień wejściowy dla strumienia reprezentowanego
przez InputStream
• BufferedInputStream(InputStream,int) – j.w., int określa
rozmiar bufora
• read() – odczytanie 1 bajtu ze strumienia buforowanego
• read(byte[], int1, int2) – odczytanie int2 bajtów ze
strumienia do tablicy i umieszczenie ich począwszy od
elementu tablicy o indeksie int1
23
24
4
27932390.018.png 27932390.019.png 27932390.020.png 27932390.021.png 27932390.022.png 27932390.023.png 27932390.024.png
Filtry bajtowe – strumienie
buforowane (strumie ń wy)
Przykład – zapis i odczyt,
strumienie buforowane
import java.io.*;
class ArgStream{
• BufferedOutputStream(OutputStream) – tworzy buforowany
strumień wyjściowy dla strumienia reprezentowanego przez
OutputStream
• BufferedOutputStream(OutputStream,int) – j.w., int określa rozmiar
bufora
• write(int) – zapisanie 1 bajtu do strumienia buforowanego
(argument int z przedziału 0-255, jeśli większy to brana jest reszta
z dzielenia całkowitego)
• write(byte[], int1, int2) – zapisanie int2 bajtów z tablicy byte[],
począwszy od elementu tablicy o indeksie int1 do strumienia
buforowanego
• dane nie zostaną przekazane do miejsca docelowego dopóki bufor
nie zostanie całkowicie wypełniony lub dopóki nie będzie
wywołana metoda flush()
//klasa ArgStream
int start=0;
int stop=25;
ArgStream(int p,int k){
start=p; stop=k; }
boolean writeStream(){
try { FileOutputStream pl=new FileOutputStream("liczby.dat");
BufferedOutputStream buff=new BufferedOutputStream(pl);
for (int out=start;out<=stop;out++){
buff.write(out); System.out.print(" "+out); }
buff.close();
return(true);
} catch(IOException e) {
System.out.println("Wyjatek:"+e.getMessage());
return false; }
25
}
26
Przykład – zapis i odczyt,
strumienie buforowane
boolean readStream(){
try { FileInputStream pl=new FileInputStream("liczby.dat");
BufferedInputStream buff=new BufferedInputStream(pl);
int in=0;
do{ in=buff.read();
if(in!=-1) System.out.print(" "+in);
} while (in!=-1);
buff.close();
return(true);
}
catch(IOException e) {
System.out.println("Wyjatek:"+e.getMessage());
return false;
}
} //koniec klasy ArgStream
Przykład – zapis i odczyt,
strumienie buforowane
public class BuforDemo {
public static void main(String[] args) {
int start=0;
int stop=25;
if (args.length>1){
start=Integer.parseInt(args[0]);
stop=Integer.parseInt(args[1]); }
else if (args.length>0)
start=Integer.parseInt(args[0]);
ArgStream as=new ArgStream(start,stop);
System.out.println("\nZapisywanie:");
boolean sukces=as.writeStream();
System.out.println("\nCzytanie:");
boolean sukcesr=as.readStream();
27
} }
28
We/wy strumienie danych
We/wy strumienie danych
• filtrują istniejące strumienie bajtowe umoŜliwiając odczyt i
zapis bezpośrednio do strumienia danych typu boolean,
double, float, int, long oraz short
• DataInputStream(InputStream) - strumień we
• DataOutputStream(OutputStream) -strumień wy
• metody:
– readBoolean(), writeBoolean()
– readByte(), writeByte()
– readDouble(), writeDouble()
– readFloat(), writeFloat ()
– readInt(), writeInt()
– readLong(), writeLong()
– readShort(), writeShort()
• dodatkowe metody:
– readUnsignedByte()
– readUnsignedShort()
• metody odczytujące ze strumieni we nie zwracają
Ŝadnej wartości wskazującej na osiągnięcie końca
odczytywania strumienia - moŜna wykorzystać
wystąpienie wyjątku EOFException (nastepuje po
osiągnięciu końca strumienia)
29
30
5
27932390.025.png 27932390.026.png 27932390.027.png 27932390.028.png 27932390.029.png 27932390.030.png 27932390.031.png 27932390.032.png
Zgłoś jeśli naruszono regulamin