Programování

Balíčky a statické importy v Javě

V mém předchozím Java 101 v tomto kurzu jste se naučili, jak lépe uspořádat kód deklarováním referenčních typů (také známých jako třídy a rozhraní) jako členů jiných referenčních typů a bloků. Také jsem vám ukázal, jak pomocí vnoření zabránit konfliktům názvů mezi vnořenými typy odkazů a typy odkazů nejvyšší úrovně, které sdílejí stejný název.

Spolu s vnořením používá Java balíčky k řešení problémů se stejným názvem v referenčních typech nejvyšší úrovně. Použití statických importů také zjednodušuje přístup ke statickým členům v zabalených referenčních typech nejvyšší úrovně. Statické importy vám ušetří stisknutí kláves při přístupu k těmto členům v kódu, ale při jejich použití je třeba si dát pozor na několik věcí. V tomto tutoriálu vás seznámím s používáním balíčků a statických importů ve vašich programech Java.

stáhnout Získat kód Stáhněte si zdrojový kód například pro aplikace v tomto výukovém programu Java. Vytvořil Jeff Friesen pro JavaWorld.

Obalové referenční typy

Vývojáři Java seskupují související třídy a rozhraní do balíčků. Použití balíčků usnadňuje vyhledání a použití referenčních typů, vyhýbání se konfliktům názvů mezi typy se stejným názvem a řízení přístupu k typům.

V této části se dozvíte o balíčcích. Zjistíte, jaké balíčky jsou, dozvíte se o balík a import příkazy a prozkoumejte další témata chráněného přístupu, soubory JAR a hledání typu.

Co jsou balíčky v Javě?

Při vývoji softwaru běžně organizujeme položky podle jejich hierarchických vztahů. Například v předchozím kurzu jsem vám ukázal, jak deklarovat třídy jako členy jiných tříd. Můžeme také použít souborové systémy k vnoření adresářů do jiných adresářů.

Použití těchto hierarchických struktur vám pomůže vyhnout se konfliktům jmen. Například v nehierarchickém systému souborů (jeden adresář) není možné přiřadit stejný název více souborům. Naproti tomu hierarchický systém souborů umožňuje souborům se stejným názvem existovat v různých adresářích. Podobně mohou dvě uzavírající třídy obsahovat vnořené třídy se stejným názvem. Konflikty názvů neexistují, protože položky jsou rozděleny do různých jmenných prostorů.

Java nám také umožňuje rozdělit referenční typy na nejvyšší úrovni (nevnořené) do více jmenných prostorů, abychom mohli lépe uspořádat tyto typy a zabránit konfliktům jmen. V Javě používáme funkci jazyka balíčku k rozdělení referenčních typů nejvyšší úrovně do více jmenných prostorů. V tomto případě a balík je jedinečný jmenný prostor pro ukládání referenčních typů. Balíčky mohou ukládat třídy a rozhraní a také dílčí balíčky, což jsou balíčky vnořené do jiných balíčků.

Balíček má název, který musí být nevyhradeným identifikátorem; například, Jáva. Operátor přístupu členů (.) odděluje název balíčku od názvu dílčího balíčku a odděluje název balíčku nebo dílčího balíčku od názvu typu. Například dvoučlenné operátory přístupu v java.lang.System samostatný název balíčku Jáva z jazyk název dílčího balíčku a samostatný název dílčího balíčku jazyk z Systém zadejte název.

Musí být deklarovány referenční typy veřejnost aby byly přístupné zvenčí jejich balíčků. Totéž platí pro všechny konstanty, konstruktory, metody nebo vnořené typy, které musí být přístupné. Jejich příklady uvidíte dále v tomto výukovém programu.

Prohlášení o balíčku

V Javě používáme výpis balíku vytvořit balíček. Tento příkaz se zobrazí v horní části zdrojového souboru a identifikuje balíček, do kterého patří typy zdrojových souborů. Musí vyhovovat následující syntaxi:

 balík identifikátor[.identifikátor]*; 

Výpis balíčku začíná vyhrazeným slovem balík a pokračuje identifikátorem, za kterým případně následuje periodicky oddělená posloupnost identifikátorů. Středník (;) ukončuje toto prohlášení.

První identifikátor (nejvíce vlevo) pojmenuje balíček a každý následující identifikátor pojmenuje dílčí balíček. Například v balíček a.b;, všechny typy deklarované ve zdrojovém souboru patří do b dílčí balíček A balík.

Konvence pojmenování balíčku / dílčího balíčku

Podle konvence vyjádříme název balíčku nebo dílčího balíčku malými písmeny. Pokud se název skládá z více slov, možná budete chtít každé slovo kromě prvního psát velkými písmeny; například, generalLedger.

Posloupnost názvů balíků musí být jedinečná, aby nedocházelo k problémům s kompilací. Předpokládejme například, že vytvoříte dva různé grafika balíčky a předpokládejme, že každý grafika balení obsahuje Trojúhelník třída s jiným rozhraním. Když překladač Java narazí na něco podobného níže, musí ověřit, že Trojúhelník (int, int, int, int) konstruktor existuje:

 Trojúhelník t = nový trojúhelník (1, 20, 30, 40); 

Ohraničující rámeček trojúhelníku

Přemýšlejte o Trojúhelník konstruktor určující ohraničující rámeček, do kterého má být trojúhelník nakreslen. První dva parametry identifikují levý horní roh pole a druhé dva parametry definují rozsahy pole.

Kompilátor prohledá všechny přístupné balíčky, dokud nenajde a grafika balíček, který obsahuje a Trojúhelník třída. Pokud nalezený balíček obsahuje příslušné Trojúhelník třída s a Trojúhelník (int, int, int, int) konstruktor, všechno je v pořádku. Jinak, pokud bude nalezen Trojúhelník třída nemá Trojúhelník (int, int, int, int) konstruktor, kompilátor hlásí chybu. (O vyhledávacím algoritmu řeknu dále v tomto tutoriálu.)

Tento scénář ilustruje důležitost výběru jedinečných sekvencí názvů balíků. Konvencí při výběru jedinečné sekvence názvů je obrácení názvu vaší internetové domény a jeho použití jako předpony sekvence. Například bych si vybral ca.javajeff jako moje předpona, protože javajeff.ca je moje doménové jméno. Pak bych upřesnil ca.javajeff.graphics.Triangle mít přístup Trojúhelník.

Součásti názvu domény a platné názvy balíků

Komponenty doménových jmen nejsou vždy platné názvy balíčků. Jeden nebo více názvů komponent může začínat číslicí (3D.com), obsahují pomlčku (-) nebo jiný nelegální znak (ab-z.com), nebo být jedním z vyhrazených slov Java (short.com). Konvence diktuje, že před číslicí předponu podtržítko (com._3D), nahraďte nelegální znak podtržítkem (com.ab_z) a doplňte vyhrazené slovo podtržítkem (com.short_).

Abyste se vyhnuli dalším problémům s výpisem balíčku, musíte dodržovat několik pravidel:

  1. Ve zdrojovém souboru můžete deklarovat pouze jeden příkaz balíčku.
  2. Výroku balíčku nemůžete předcházet nic kromě komentářů.

První pravidlo, které je zvláštním případem druhého pravidla, existuje, protože nemá smysl ukládat referenční typ do více balíčků. Ačkoli balíček může uložit více typů, typ může patřit pouze jednomu balíčku.

Když zdrojový soubor nedeklaruje příkaz balíčku, říká se, že typy zdrojového souboru patří do nepojmenovaný balíček. Non-triviální referenční typy jsou obvykle uloženy v jejich vlastních balíčcích a vyhýbají se nepojmenovanému balíčku.

Implementace Java mapují názvy balíků a dílčích balíků na stejnojmenné adresáře. Například implementace by mapovala grafika do adresáře s názvem grafika. V případě balíčku a. bprvní písmeno, A namapuje na adresář s názvem A a b by mapoval na a b podadresář A. Kompilátor ukládá soubory třídy, které implementují typy balíčku, do odpovídajícího adresáře. Nepojmenovaný balíček odpovídá aktuálnímu adresáři.

Příklad: Zabalení zvukové knihovny do prostředí Java

Praktický příklad je užitečný pro úplné uchopení balík prohlášení. V této části předvádím balíčky v kontextu zvukové knihovny, která vám umožní číst zvukové soubory a získávat zvuková data. Pro stručnost uvedu pouze kosterní verzi knihovny.

Zvuková knihovna v současné době sestává pouze ze dvou tříd: Zvuk a WavReader. Zvuk popisuje zvukový klip a je hlavní třídou knihovny. Výpis 1 představuje svůj zdrojový kód.

Výpis 1. Příklad výpisu balíčku (Audio.java)

 balíček ca.javajeff.audio; veřejné závěrečné audio ukázky {private int []; private int sampleRate; Zvuk (int [] ukázky, int sampleRate) {this.samples = ukázky; this.sampleRate = sampleRate; } public int [] getSamples () {vrátit vzorky; } public int getSampleRate () {návrat sampleRate; } veřejné statické Zvuk newAudio (název souboru řetězce) {if (název souboru.toLowerCase (). endsWith (". wav")) vrátit WavReader.read (název souboru); else return null; // nepodporovaný formát } } 

Pojďme projít výpisem 1 krok za krokem.

  • The Audio.java soubor v seznamu 1 ukládá soubor Zvuk třída. Tento seznam začíná výpisem balíku, který identifikuje ca.javajeff.audio jako balíček třídy.
  • Zvuk je deklarováno veřejnost takže na něj lze odkazovat zvenčí jeho balíčku. Také je to deklarováno finále takže ji nelze rozšířit (tj. podtřídu).
  • Zvuk prohlašuje soukroméVzorky a vzorkovací frekvence pole pro uložení zvukových dat. Tato pole jsou inicializována na hodnoty předané Zvukkonstruktor.
  • Zvukje deklarován konstruktor balíček-soukromý (to znamená, že konstruktor není deklarován veřejnost, soukroménebo chráněný), takže tuto třídu nelze vytvořit z vnější strany jejího balíčku.
  • Zvuk představuje getSamples () a getSampleRate () metody vrácení vzorků zvukového klipu a vzorkovací frekvence. Každá metoda je deklarována veřejnost aby jej bylo možné volat zvenčí Zvukbalíček.
  • Zvuk uzavírá a veřejnost a statickýnewAudio () tovární metoda pro vrácení Zvuk objekt odpovídající název souboru argument. Pokud nelze získat zvukový klip, nula je vrácen.
  • newAudio () srovnává název souborurozšíření s .wav (tento příklad podporuje pouze zvuk WAV). Pokud se shodují, provede se vrátit WavReader.read (název souboru) vrátit Zvuk objekt se zvukovými daty založenými na WAV.

Výpis 2 popisuje WavReader.

Výpis 2. Pomocná třída WavReader (WavReader.java)

 balíček ca.javajeff.audio; finální třída WavReader {statické čtení zvuku (název souboru řetězce) {// Přečtěte si obsah souboru názvu souboru a zpracujte jej // do pole vzorových hodnot a vzorkovací frekvence // hodnoty. Pokud soubor nelze přečíst, vraťte null. Pro // stručnost (a protože jsem ještě nediskutoval o Java // souborových I / O API), uvádím pouze skeletální kód, který // vždy vrací audio objekt s výchozími hodnotami. vrátit nový zvuk (nový int [0], 0); }} 

WavReader je určen ke čtení obsahu souboru WAV do souboru Zvuk objekt. (Třída bude nakonec větší s dalšími soukromé pole a metody.) Všimněte si, že tato třída není deklarována veřejnost, který dělá WavReader přístupné Zvuk ale ne kódovat mimo ca.javajeff.audio balík. Myslet na WavReader jako pomocná třída, jejíž jediným důvodem existence je sloužit Zvuk.

Chcete-li vytvořit tuto knihovnu, proveďte následující kroky:

  1. Jako aktuální adresář vyberte vhodné umístění ve vašem systému souborů.
  2. Vytvořit ca / javajeff / audio hierarchie podadresářů v aktuálním adresáři.
  3. Zkopírujte výpisy 1 a 2 do souborů Audio.java a WavReader.java, v uvedeném pořadí; a uložte tyto soubory do Zvuk podadresář.
  4. Za předpokladu, že aktuální adresář obsahuje ca. podadresář, spustit javac ca / ​​javajeff / audio / *. java zkompilovat dva zdrojové soubory do ca / javajeff / audio. Pokud vše půjde dobře, měli byste objevit Audio.class a WavReader.class soubory v Zvuk podadresář. (Alternativně v tomto příkladu můžete přepnout na Zvuk podadresář a spustit javac * .java.)

Nyní, když jste vytvořili zvukovou knihovnu, budete ji chtít použít. Brzy se podíváme na malou aplikaci Java, která předvádí tuto knihovnu. Nejprve se musíte dozvědět více o prohlášení o importu.

Prohlášení o importu Java

Představte si, že to musíte specifikovat ca.javajeff.graphics.Triangle pro každý výskyt Trojúhelník ve zdrojovém kódu opakovaně. Java poskytuje prohlášení o importu jako pohodlnou alternativu pro vynechání zdlouhavých podrobností balíčku.

Prohlášení o importu importuje typy z balíčku sdělením kompilátoru, kde má hledat nekvalifikovaný (bez předpony balíčku) názvy typů během kompilace. Zobrazuje se v horní části zdrojového souboru a musí odpovídat následující syntaxi:

 import identifikátor[.identifikátor]*.(název_typu | *); 

Výpis importu začíná vyhrazeným slovem import a pokračuje identifikátorem, za kterým případně následuje periodicky oddělená posloupnost identifikátorů. Název typu nebo hvězdička (*) následuje a středník tento příkaz ukončí.

Syntaxe odhaluje dvě formy příkazu importu. Nejprve můžete importovat jeden název typu, který je identifikován pomocí název_typu. Zadruhé můžete importovat všechny typy, které jsou označeny hvězdičkou.

The * symbol je zástupný znak, který představuje všechny nekvalifikované názvy typů. Říká kompilátoru, aby hledal takové názvy v balíčku nejvíce vpravo v pořadí balíků příkazu importu, pokud není název typu nalezen v dříve prohledávaném balíčku. Všimněte si, že použití zástupného znaku nemá výkonnostní trest ani nevede k nafouknutí kódu. Může to však vést ke konfliktům jmen, které uvidíte.

Například, import ca.javajeff.graphics.Triangle; říká kompilátoru, že nekvalifikovaný Trojúhelník třída existuje v ca.javajeff.graphics balík. Podobně něco jako

 importovat ca.javajeff.graphics. *; 

řekne kompilátoru, aby se v tomto balíčku podíval, když narazí na Trojúhelník jméno, a Kruh jméno, nebo dokonce Účet jméno (pokud Účet ještě nebyl nalezen).

Vyhněte se * v projektech pro více vývojářů

Při práci na projektu pro více vývojářů nepoužívejte * zástupný znak, aby ostatní vývojáři mohli snadno zjistit, které typy se používají ve zdrojovém kódu.

$config[zx-auto] not found$config[zx-overlay] not found