Java 101: Paketi organiziraju klase i sučelja

Zašto izumiti kotač? Taj se kliše odnosi na razvoj softvera gdje neki programeri često prepisuju isti kod za različite programe. Dva nedostatka takvog pristupa su:

  1. Troši vrijeme
  2. Uvodi potencijal za bugove u ispravljenom kodu

Kao alternativu prepisivanju istog koda, mnoga okruženja za razvoj softvera nude bibliotečki alat koji organizira često korišteni kôd. Nakon što programeri dovrše ispravljanje pogrešaka nekog koda za višekratnu upotrebu, oni koriste alat za spremanje tog koda u knjižnicu - jednu ili više datoteka koje sadrže često korišten kôd za upotrebu u raznim programima. Tijekom izrade programa, kompajler ili alat knjižnice pristupa knjižnici kako bi povezao programski kod s referencom na biblioteku programa.

Knjižnice su temelj Java. Omogućuju, djelomično, učitač klasa JVM-a da pronađe datoteke predavanja. (Istražit ću učitavače klasa u budućem članku.) Iz tog su razloga Javine knjižnice obično poznate kao knjižnice razreda. Međutim, Java biblioteke klasa naziva paketima.

Ovaj članak istražuje pakete; Pokazat ću vam kako stvoriti pakete klasa i sučelja, kako uvesti (odnosno unijeti u program) upakirane klase i sučelja, kako premjestiti pakete na tvrdi disk i kako koristiti jar datoteke za enkapsuliranje paketa.

Bilješka
Eksperiment s jednim paketom u ovom članku specifičan je za Microsoft Windows. Ovaj biste eksperiment trebali moći lako ekstrapolirati na platforme koje nisu Windows.

Što su paketi?

Paket je skup više klase i sučelja. Svaki paket ima svoje ime i organizira svoje klase i sučelja najviše razine (to jest nesastavljena) u zasebni prostor imena ili zbirku imena. Iako se istoimene klase i sučelja ne mogu pojaviti u istom paketu, mogu se pojaviti u različitim paketima jer svakom paketu dodjeljuje zasebni prostor imena.

Iz perspektive implementacije, poistovjećivanje paketa s direktorijom pokazuje se korisnim, kao i izjednačavanje klasa paketa i sučelja s datotekama klasa direktorija. Imajte na umu i druge pristupe - poput upotrebe baza podataka - implementaciji paketa, stoga nemojte imati naviku uvijek izjednačavati pakete s direktorijima. No budući da mnogi JVM-ovi koriste direktorije za implementaciju paketa, ovaj članak izjednačava pakete s direktorijima. Java 2 SDK organizira svoju široku kolekciju klasa i sučelja u hijerarhiju paketa unutar paketa nalik stablu, što je ekvivalentno direktorijima unutar direktorija. Ta hijerarhija omogućuje Sun Microsystemsima da lako distribuiraju (i vi lako radite) te klase i sučelja. Primjeri Java paketa uključuju:

  • java.lang:Zbirka klasa povezanih s jezikom, kao što je Objecti String, organizirana u potpaketu javapaketalang
  • java.lang.ref:Zbirka jezičnih klase referentnih vezane, kao što je SoftReferencei ReferenceQueueorganizirala u refsub-podpaketa od javapaket je langpodpaketa
  • javax.swing:Zbirka klasa komponenata povezanih s Swingom, kao što su JButtonsučelja, kao što su ButtonModelorganizirana u potpaketu javaxpaketaswing

Znakovi razdoblja odvajaju nazive paketa. Na primjer, u javax.swing, znak razdoblja razdvaja naziv paketa javaxod naziva podpaketa swing. Znak razdoblja neovisno je o platformi ekvivalent znakova kosa crta ( /), znakova obrnute kose crte ( \) ili drugih znakova za odvajanje imena direktorija u implementaciji paketa temeljenog na direktorij, grana baze podataka u hijerarhijskoj implementaciji paketa temeljenih na bazi podataka, i tako dalje .

Savjet
Kao što ne možete pohraniti i datoteku i direktorij s identičnim imenima u isti direktorij, ne možete pohraniti klasu ili sučelje i paket s identičnim imenima u isti paket. Na primjer, s obzirom na naziv paketa accounts, ne možete pohraniti i paket i klasu imenovanu payableu accounts. Da biste izbjegli sukobljena imena, velikim slovima upišite prvo slovo naziva klase i sučelja, a malim slovom prvo slovo imena paketa. Koristeći prethodni primjer, pohranite klasu Payableu paket accountskao accounts.Payablei paket payableu paket accountskao accounts.payable. Saznajte više o ovoj i drugim konvencijama imenovanja iz Sun-ovih konvencija koda za programski jezik Java .

Stvorite paket klasa i sučelja

Klase i sučelja svake izvorne datoteke organiziraju se u paket. U packagenedostatku direktive, te klase i sučelja pripadaju neimenovanom paketu (direktorij koji JVM smatra trenutnim direktorijumom - direktorij u kojem Java program započinje s izvršenjem putem programa Windows java.exeili ekvivalent OS-u - i ne sadrži potpakete) . Ali ako se packagedirektiva pojavi u izvornoj datoteci, ta direktiva imenuje paket za te klase i sučelja. Koristite sljedeću sintaksu da odredite packagedirektivu u izvornom kodu:

'paket' ime_paketa ['.' subpackageName ...] ';'

packageDirektiva počinje s packageključnom riječi. Identifikator da imena paket, packageName, odmah slijedi. Ako se klase i sučelja trebaju pojaviti u potpaketu (na nekoj razini) unutar packageName, jedan ili više subpackageNameidentifikatora odvojenih razdobljem pojavljuju se nakon packageName. Sljedeći fragment koda predstavlja par packagedirektiva:

paketna igra; paketna igra.uređaji;

Prva packagedirektiva identificira paket s imenom game. Sve klase i sučelja koja se pojavljuju u izvornoj datoteci te direktive organiziraju se u gamepaketu. Druga packagedirektiva identificira podpaket s imenom deviceskoji se nalazi u paketu s imenom game. Sve klase i sučelja koja se pojavljuju u izvornoj datoteci te direktive organiziraju se u potpaketu gamepaketa devices. Ako JVM implementacija mapira imena paketa u nazive direktorija, game.devicesmapira u game\deviceshijerarhiju direktorija pod Windowsom i game/deviceshijerarhiju direktorija pod Linuxom ili Solarisom.

Oprez
Samo se jedna packagedirektiva može pojaviti u izvornoj datoteci. Nadalje, packagedirektiva mora biti prvi kod (osim komentara) u toj datoteci. Kršenje bilo kojeg pravila uzrokuje da Java-ov prevoditelj prijavi pogrešku.

Kako bih vam pomogao da se ugodno snađete s paketima, pripremio sam primjer koji obuhvaća sve teme u ovom članku. U ovom ćete odjeljku naučiti kako stvoriti paket primjera. U kasnijim odjeljcima naučit ćete kako iz ovog paketa uvesti klasu i sučelje, kako premjestiti ovaj paket na drugo mjesto na tvrdom disku i dalje pristupati paketu iz programa te kako spremiti paket u jar datoteku . Popis 1 predstavlja izvorni kod paketa:

Popis 1. A.java

// paket A.java testpkg; javna klasa A {int x = 1; javni int y = 2; zaštićen int z = 3; int returnx () {return x; } public int returny () {return y; } zaštićen int returnz () {return z; } javno sučelje StartStop {void start (); void stop (); }} klasa B {javna statička void hello () {System.out.println ("hello"); }}

Popis 1 uvodi izvorni kod u vaš prvi imenovani paket. U package testpkg;direktiva imena tog paketa testpkg. Unutar testpkgsu razredi Ai B. Unutar Asu tri deklaracije polja, tri deklaracije metode i deklaracija unutarnjeg sučelja. Unutar Bje jedna metoda izjava. Cjelokupni izvorni kod pohranjuje A.javajer Aje javna klasa. Naš zadatak: Pretvorite ovaj izvorni kod u paket koji se sastoji od dvije klase i unutarnjeg sučelja (ili direktorija koji sadrži tri datoteke klasa). Sljedeći koraci specifični za Windows izvršavaju taj zadatak:

  1. Otvorite Windows naredbeni prozor i osigurajte da se nalazite u c:korijenskom direktoriju pogona (glavni direktorij - predstavljen početnim \znakom nagnuta crta ( ). Da biste to učinili, upišite c:naredbu nakon koje slijedi cd \naredba. (Ako koristite drugi pogon, zamijenite ga c:odabranim pogonom. Također, ne zaboravite pritisnuti tipku Enter nakon unosa naredbe.)
  2. Stvorite testpkgdirektorij upisivanjem md testpkg. Napomena: Kad slijedite korake ovog članka, ne upisujte točke nakon naredbi.
  3. Provjerite testpkgtrenutni direktorij upisivanjem cd testpkg.
  4. Upotrijebite uređivač za unos izvornog koda izlistavanja 1 i spremite ga u A.javadatoteku u testpkg.
  5. Sastavite A.javatipkanjem javac A.java. Te bi trebao vidjeti classfiles A$StartStop.class, A.classi B.classpojavljuju se u testpkgimenik.

Slika 1 ilustrira korake od 3 do 5.

Čestitamo! Upravo ste kreirali svoj prvi paket. Zamislite da ovaj paket sadrži dvije klase ( Ai B) i Ajedinstveno unutarnje sučelje ( StartStop). Također se možete sjetiti tog paketa kao katalog sadrži tri classfiles: A$StartStop.class, A.classi B.class.

Bilješka
To minimize package name conflicts (especially among commercial packages), Sun has established a convention in which a company's Internet domain name reverses and prefixes a package name. For example, a company with x.com as its Internet domain name and a.b as a package name (a) followed by a subpackage name (b) prefixes com.x to a.b, resulting in com.x.a.b. My article does not follow this convention because the testpkg package is a throw-away designed for teaching purposes only.

Import a package's classes and interfaces

Once you have a package, you will want to import classes and/or interfaces—actually, class and/or interface names—from that package to your program, so it can use those classes and/or interfaces. One way to accomplish that task is to supply the fully qualified package name (the package name and all subpackage names) in each place where the reference type name (the class or interface name) appears, as Listing 2 demonstrates:

Listing 2. Usetestpkg1.java

// Usetestpkg1.java class Usetestpkg1 implements testpkg.A.StartStop { public static void main (String [] args) { testpkg.A a = new testpkg.A (); System.out.println (a.y); System.out.println (a.returny ()); Usetestpkg1 utp = new Usetestpkg1 (); utp.start (); utp.stop (); } public void start () { System.out.println ("Start"); } public void stop () { System.out.println ("Stop"); } } 

By prefixing testpkg. to A, Usetestpkg1 accesses testpkg's class A in two places and A's inner interface StartStop in one place. Complete the following steps to compile and run Usetestpkg1:

  1. Open a Windows command window and make sure you are in the c: drive's root directory.
  2. Ensure the classpath environment variable does not exist by executing set classpath=. (I discuss classpath later in this article.)
  3. Use an editor to enter Listing 2's source code and save that code to a Usetestpkg1.java file in the root directory.
  4. Compile Usetestpkg1.java by typing javac Usetestpkg1.java. You should see classfile Usetestpkg1.class appear in the root directory.
  5. Type java Usetestpkg1 to run this program.

Figure 2 illustrates Steps 3 through 5 and shows the program's output.

According to Usetestpkg1's output, the main() method's thread successfully accesses testpkg.A's y field and calls the returny() method. Furthermore, the output shows a successful implementation of the testpkg.A.StartStop inner interface.

For Usetestpkg1, prefixing testpkg. to A in three places doesn't seem a big deal. But who wants to specify a fully qualified package name prefix in a hundred places? Fortunately, Java supplies the import directive to import a package's public reference type name(s), so you do not have to enter fully qualified package name prefixes. Express an import directive in source code via the following syntax:

'import' packageName [ '.' subpackageName ... ] '.' ( referencetypeName | '*' ) ';' 

An import directive consists of the import keyword immediately followed by an identifier that names a package, packageName. An optional list of subpackageName identifiers follows to identify the appropriate subpackage (if necessary). The directive concludes with either a referencetypeName identifier that identifies a specific class or interface from the package, or an asterisk (*) character. If referencetypeName appears, the directive is a single-type import directive. If an asterisk character appears, the directive is a type-on-demand import directive.

Caution
As with the package directive, import directives must appear before any other code, with three exceptions: a package directive, other import directives, or comments.

The single-type import directive imports the name of a single public reference type from a package, as the following code fragment demonstrates:

import java.util.Date; 

The previous single-type import directive imports class name Date into source code. As a result, you specify Date instead of java.util.Date in each place that class name appears in source code. For example, when creating a Date object, specify Date d = new Date (); instead of java.util.Date d = new java.util.Date ();.

Pazite s jednotipskim importsmjernicama. Ako kompajler otkrije jednotipsku importdirektivu koja navodi naziv referentnog tipa koji je također deklariran u izvornoj datoteci, kompajler prijavljuje pogrešku, kao što pokazuje sljedeći fragment koda:

import java.util.Date; Datum predavanja {}

Kompajler fragment koda smatra pokušajem uvođenja dviju referentnih vrsta s istim Dateimenom: