Jason. Cała informatyka w jednym miejscu!

Kolejna porcja Javy! Dzisiaj sobie wyjaśnimy dlaczego pakiety tworzone za pomocą słowa "package" w języku Java są szeroko wykorzystywane. Może Wy jesteście zainteresowani powodami stosowania pakietów i zasad ich wykorzystywania w praktyce :)?

"PACKAGE" W JĘZYKU JAVA. DEFINICJA I POWODY TWORZENIA PAKIETÓW

Pakiet stanowi grupę czy też podzbiór utworzonych klas celem posegregowania ich według przeznaczenia. Działa to identycznie jak ma to miejsce w drzewie katalogów. Filmy pakujemy do filmów, obrazki do obrazków, a skróty jak nie mieszczą się na pulpicie, to też powinniśmy znaleźć dla nich folder :). W Javie wcale nie jest inaczej, aczkolwiek trzeba wiedzieć że to NIE JEST jedyny powód ich stosowania :D.

Jeżeli zajrzymy do dokumentacji, to zauważymy, że wszystko ma swoje miejsce i swój własny pakiet. A ten pakiet może mieć własne inne pakiety i dopiero te "podpakiety" mogą dysponować klasami. Słynna kolekcja "ArrayList" na przykład pochodzi z pakietu "util" (skrót od "utilities"), a ten pakiet z kolei należy do rodziny wszystkich pakietów, "java". W ten sposób mamy ten sam ciąg, który widzimy wielokrotnie podczas importowania, "java. util.ArrayList". Gdy korzystaliśmy z "BufferedReader", to też musieliśmy zaimportować stosowny pakiet (nie bibliotekę!). Zatem sięgaliśmy do "java", "io" i tam mieliśmy "BufferedReader".

Słowo kluczowe "package" w języku Java jest wykorzystywane jeszcze z jednego powodu: minimalizuje szansę na wystąpienie kolizji nazw! Jest pewne na 99%, że pracując w zespole ktoś wymyśli taką samą nazwę jak Wy. Zatem trzeba nasz pakiet osadzić w większy pakiet, który będzie miał bardziej unikatową nazwę.

PRZYJĘTA KONWENCJA NAZEWNICZA DLA PAKIETÓW

Tak się składa, że wprowadzono obowiązującą konwencję nazewniczą. Przyjęło się, że pakiety tworzone przy użyciu "package" w języku Java powinny mieć strukturę nazewniczą w postaci odwróconej nazwy naszej domeny. Tak więc podstawiając pod mój przypadek, należałoby zapisać to tak:

package pl.jasonxiii.[nazwa klasy];

Dzięki temu, jest możliwość zminimalizowania występowania kolizji nazw w przypadku, gdyby ktoś inny na przykład zaimportował mój pakiet i też zbudowałby klasę o tej samej nazwie. Mimo tego, że klasy nosiłyby tę samą nazwę, to wyróżniałyby je nazwy pakietów i w ten sposób problem znika :).

PEŁNA NAZWA KLASY W PAKIECIE I WPŁYW IMPORTU

Pamiętajcie, że w sytuacji, kiedy dana klasa należy do pakietu, to w rzeczywistości otrzymuje pełną nazwę o postaci przedstawionej u góry. Dlatego też w przypadku próby skorzystania z tej samej nazwy klasy pochodzącej z dwóch różnych pakietów, trzeba wobec jednej z nich wprowadzić pełną nazwę tj. cały ciąg pakietów! To pokazuje, że import pakietu ma za zadanie jedynie skrócić ciąg do samej nazwy klasy:

import pl.jasonxiii.exampleA.Example;

public class Main {
	public static void main(String[] args) {
		Example exampleA = new Example();
		pl.jasonxiii.exampleB.Example exampleB = new pl.jasonxiii.exampleB.Example();
	}
}

Na tym kodzie źródłowym widzimy już doskonale jak wygląda ciąg "pełny" i "skrócony" przez import pakietu.

KOMPILOWANIE KODU Z PAKIETÓW

Kompilując to wszystko ręcznie przy użyciu jedynie wiersza poleceń, na pewno niejeden z Was zastanawiał się czemu znowu coś nie działa. Dzisiaj nikogo nie będzie dziwić korzystanie z dowolnego IDE, aczkolwiek warto chociaż parę razy w życiu skompilować swój kod manualnie od początku do końca, aby się dowiedzieć jak to działa w rzeczywistości. Pakiety w języku Java mocno komplikują proces ręcznej kompilacji i tym się teraz zajmiemy, zanim zakończę temat.

Tym razem zapodam jedną jedyną klasę, która przyda się do eksperymentu. Zróbcie sobie nowy katalog, a w nim utwórzcie "ciąg" podfolderów, które MUSZĄ odpowiadać ciągowi podanemu po słowie kluczowym "package" w języku Java. Czyli w folderze głównym tworzycie folder o nazwie "X", a w nim tworzycie kolejny folder "Y" (możecie po nim dać jeszcze więcej). Właśnie tam zapiszcie plik z rozszerzeniem ".java" wklejając poniższą zawartość:

package [X].[Y];

public class Main {
	public static void main(String[] args) {
		System.out.println("Program działa!");
	}
}

Pakiety w języku Java są niczym innym jak ciągiem podfolderów, które przypominają strukturę drzewa. Po każdej kropce "schodzi się" poziom niżej i w ten sposób można dostać się w każde miejsce zaczynając od "korzenia", jakim jest nasz folder główny. Po zapisaniu pliku z rozszerzeniem ".java", otwórzcie sobie wiersz poleceń (najlepiej z uprawnieniami administratora) i przy pomocy polecenia "cd", przejdźcie bezpośrednio do katalogu posiadającego folder o nazwie "X". Wpisując poniższe polecenie:

javac [X]/[Y]/[nazwa pliku źródłowego].java

kompilator Javy przejdzie wówczas po wszystkich katalogach jeden po drugim i skompiluje program, o ile ciąg po słowie "package" w języku Java zgadza się ze wszystkimi podfolderami. Pakiety są wyjątkowo czułe na literówki, więc w przypadku wystąpienia błędu, upewnijcie się że wpisaliście wszystkie nazwy perfekcyjnie. Znaki diakrytyczne najlepiej obejść szerokim łukiem. Jeżeli poprzednie polecenie niczego nie wypisuje, to znak że kompilacja się udała. W celu uruchomienia skompilowanego programu, zostajemy w tym samym folderze i wpisujemy to:

java [X].[Y].Main

Zwróćcie uwagę, że teraz są kropki zamiast slash'y, tak jak się wpisało w kodzie po słowie kluczowym "package"! Też wyjątkowo łatwo się pomylić, więc pozostaje Wam tylko "wejście w krew". Jeżeli kompilacja, to znaki ukośników. Jeżeli uruchamianie, to kropki. Przyjrzyjcie się poniższemu obrazkowi i zobaczcie jakie są różnice:

Podfoldery pakietu w języku Java

Pakiety tworzą "drzewiastą" strukturę katalogów, która umożliwia segregację plików źródłowych i klasowych.

Stosowanie pakietów i ich właściwe rozumienie jest KLUCZOWE przy wykorzystywaniu archiwum JAR oraz tzw. "manifestu".


To było wyjaśnienie i teoretyczne, i praktyczne. Słowo kluczowe "package" w języku Java powinno być wykorzystywane W KAŻDYM Waszym programie i należy to robić z głową, nieważne czy z pomocą IDE, czy nie.

PODOBNE ARTYKUŁY