4. Pakiety i importy
Pakiety są swoistymi bibliotekami klas. Każda taka biblioteka (pakiet) grupuje
klasy, które mają jakąś wspólną funkcjonalność np. służą do operacji we-wy,
budowy aplikacji sieciowych itp.
Każda klasa należy do jakiegoś pakietu.
Klasy kompilowane z deklaracją pakietu package ... należą do pakietu o nazwie podanej w deklaracji.
Klasy kompilowane bez deklaracji pakietu należę do pakietu "bez nazwy" (domyślnego).
Pakiet bez nazwy jest definiowany przez środowisku w którym działa Java (zwykle
jest to bieżący katalog, ale może to być też jakaś tablica w bazie danych).
Pakiety mają hierarchiczna strukturę:
Pakiet
podpakiet
podpakiet
Np. pakiet o nazwie java.awt zawiera podpakiet o nazwie java.awt.event.
Pakiet jest pojęciem logicznym. Hierarchiczna struktura pakietów może być
odwzorowywana w różny fizyczny sposób. Typowym jest struktura katalogów (kolejne
poziomy hierarchii katalogów odpowiadają kolejnym poziomom hierarchii pakietów).
W katalogach "terminalnych" znajdują się pliki klasowe (.class) stanowiące
użytkowe klasy danej "biblioteki". Ponieważ struktury katalogowe dają się
łatwo archiwizować, to pakiety klas są zwykle przechowywane w plikach JAR
lub ZIP.
Ale nie jest to jedyny możliwy sposób organizacji. Wszystko zależy od środowiska
w którym działa Java. Pakiety klas mogą być (i bywają) przechowywane np.
w bazach danych.
Java wyposażona jest w ok. setki pakietów (o
których możemy myśleć jak o bibliotekach standardowych), które z kolei zawierają
tysiące klas. Pakiety są umieszczone w plikach JAR (archiwach), zawartych
w dystrubacjach Javy.
Po co są pakiety?
Zadaniem pakietów jest nie tylko grupowanie klas wedlug ich funkcjonalności.
Rozważmy przykład:
class A {
Button b = new Button("Ok"); // tworzymy obiekt klasy Button
....
}
Możliwe są dwa przypadki: klasa Button jest zdefiniowana w tym samym pliku
lub w pliku z katalogu bieżącego ALBO klasa Button jest zewnętrzna.
W pierwszym przypadku kompilator (i JVM) mogą odnaleźć potrzebną klasę.
W drugim - powstaje problem gdzie jej szukać.
Co więcej, użycie nazwy Button może być niejednoznaczne (może chodzi o Button
z bieżącego pliku, a może o Button skądś z zewnątrz).
Zatem pakiety, których zadaniem jest grupowanie klas pełnią rolę porządkującą
względem przestrzeni nazw klas i chronią przed kolizjami nazw.
Nazwy kwalifikowane
Kwalifikowana nazwa klasy (typu) znajdującej się w nazwanym pakiecie ma postać:
nazwa_pakietu.nazwa_klasy
np. java.awt.Button
class A {
java.awt.Button b = new java.awt.Button("Ok");
....
}
Klasy zdefiniowane w nienazwanym pakiecie (np. w pliku źródłowym) mają jako kwalifikowane swoje proste nazwy (czyli np. Para).
Generalnie wszystkie nazwy klas użytych w programie winny być kwalifikowane.
Na szczęście, deklaracja importu pozwala na użycie nazw uproszczonych
import java.awt.Button; // importuje nazwę klasy java.awt.Button
class A {
java.awt.Frame f = new java.awt.Frame("Tytuł");
Button b = new Button("Ok"); // użycie prostej nazwy klasy java.awt.Button
....
}
Powyżej po importowaniu nazwy klasy java.awt.Button możemy użyć jej uproszczonej
nazwy Button. Ale ponieważ nie importowaliśmy nazwy klasy java.awt.Frame
jesteśmy zmuszeni używać jej pełnej kwalifikowanej nazwy.
Wygodna forma deklaracji importu pozwala importować nazwy wszystkich klas danego pakietu. Do tego służy gwiazdka.
import java.awt.*; // importuje wszystkie nazwy klas pakietu java.awt
class A {
Frame f = new Frame("Tytuł"); // teraz możemy użyć też prostej nazwy
// klasy java.awt.Frame
Button b = new Button("Ok");
....
}
Znaleźliśmy zatem wyjaśnienie tajemniczych napisów import... , które pojawiały
się w aplikacjach powitalnych (wykład 4) oraz w przykładach wykorzystujących
dialogi z klasy JOptionPane.
A co z klasami String i System, których nazw często używamy w przykładach?
One też stanowią standardowe klasy Javy. I znajdują się w określonym pakiecie (java.lang).
Pakiet java.lang nie wymaga importu (m.in zawiera klasy String i System)
Nazwy klas tego pakietu są importowane domyślnie.
Uwaga. Importowanie nazw klas nie oznacza "wstawiania" ich definicji
do naszego programu źródłowego. Wielkość programu nie zależy od liczby importowanych
nazw, a import służy tylko i wyłącznie umożliwieniu posługiwania się skróconymi
nazwami klas i stanowi sygnał dla kompilatora i JVM gdzie, w jakich pakietach
szukać definicji tych klas.
|