Programmering

Java 101: Pakker organiserer klasser og grænseflader

Hvorfor genopfinde hjulet? Denne kliche gælder for softwareudvikling, hvor nogle udviklere ofte omskriver den samme kode til forskellige programmer. To ulemper ved denne tilgang er:

  1. Det spilder tid
  2. Det introducerer potentialet for fejl i fejlretningskode

Som et alternativ til omskrivning af den samme kode leverer mange softwareudviklingsmiljøer et biblioteksværktøj, der organiserer ofte brugt kode. Når udviklere er færdige med at debugge en eller anden genanvendelig kode, bruger de værktøjet til at gemme den kode i en bibliotek—En eller flere filer, der indeholder kode, der ofte bruges til brug i forskellige programmer. Under programopbygning får compileren eller biblioteksværktøjet adgang til biblioteket for at forbinde programmets bibliotekshenviste kode til programmet.

Biblioteker er grundlæggende for Java. De tillader delvis JVM's klasselæsser at finde klassefiler. (Jeg vil udforske classloaders i en fremtidig artikel.) Af den grund er Java's biblioteker almindeligvis kendt som klassebiblioteker. Java henviser imidlertid til klassebiblioteker som pakker.

Denne artikel udforsker pakker; Jeg viser dig, hvordan du opretter pakker med klasser og grænseflader, hvordan du importerer (dvs. bringer ind i et program) pakkede klasser og grænseflader, hvordan du flytter pakker på harddisken, og hvordan du bruger jar-filer til at indkapsle pakker.

Bemærk
Denne artikels enkeltpakkeeksperiment er Microsoft Windows-specifikt. Du skal være i stand til nemt at ekstrapolere dette eksperiment til ikke-Windows-platforme.

Hvad er pakker?

EN pakke er en samling af klasser og grænseflader. Hver pakke har sit eget navn og organiserer sine topklasser (dvs. ikke-tilknyttede) klasser og grænseflader i en separat navneområde, eller navnesamling. Selvom samme navngivne klasser og grænseflader ikke kan vises i den samme pakke, kan de vises i forskellige pakker, fordi et separat navneområde tildeles hver pakke.

Fra et implementeringsperspektiv viser det sig nyttigt at sidestille en pakke med et bibliotek, ligesom det at ligestille en pakke klasser og grænseflader med et biblioteks klassefiler. Husk andre tilgange - f.eks. Brug af databaser - til implementering af pakker, så vær ikke vant til altid at sidestille pakker med mapper. Men fordi mange JVM'er bruger mapper til at implementere pakker, sidestiller denne artikel pakker med mapper. Java 2 SDK organiserer sin enorme samling af klasser og grænseflader i et trælignende hierarki af pakker inden for pakker, hvilket svarer til mapper i mapper. Dette hierarki giver Sun Microsystems mulighed for let at distribuere (og du nemt kan arbejde med) disse klasser og grænseflader. Eksempler på Java-pakker inkluderer:

  • java.lang: En samling af sprogrelaterede klasser, såsom Objekt og Snor, organiseret i java pakke er lang underpakke
  • java.lang.ref: En samling af referencerelaterede sprogklasser, såsom SoftReference og ReferenceKue, organiseret i ref underpakke af java pakke er lang underpakke
  • javax.swing: En samling af Swing-relaterede komponentklasser, såsom JButton, og grænseflader, såsom ButtonModel, organiseret i javax pakke er svinge underpakke

Periode tegn adskiller pakkenavne. For eksempel i javax.swing, et periodetegn adskiller pakkens navn javax fra underemballage navn svinge. En periodekarakter er den platformuafhængige ækvivalent med skråstregtegn (/), tilbageslagstegn (\) eller andre tegn til at adskille katalognavne i en biblioteksbaseret pakkeimplementering, databasegrener i en hierarkisk databasebaseret pakkeimplementering osv.

Tip
Ligesom du ikke kan gemme både en fil og en mappe med identiske navne i samme bibliotek, kan du ikke gemme en klasse eller grænseflade og en pakke med identiske navne i samme pakke. For eksempel givet en pakke med navnet konti, kan du ikke gemme både en pakke og en klasse med navnet betales i konti. For at undgå modstridende navne skal du bogstaver det første bogstav i klasse- og grænsefladenavne og med små bogstaver i pakkenavnene. Brug det foregående eksempel, butiksklasse Betales i pakke konti som konti. Betales og pakke betales i pakke konti som konti. betales. Lær mere om dette og andre navngivningskonventioner fra Suns Kodekonventioner til Java-programmeringssprog.

Opret en pakke med klasser og grænseflader

Hver kildefils klasser og grænseflader organiseres i en pakke. I pakke direktivets fravær, disse klasser og grænseflader hører til den ikke-navngivne pakke (den mappe, som JVM betragter som den aktuelle mappe - den mappe, hvor et Java-program begynder at udføre det via Windows java.exe, eller OS-ækvivalent, program - og indeholder ingen underpakker). Men hvis den pakke direktivet vises i en kildefil, hvor direktivet navngiver pakken til disse klasser og grænseflader. Brug følgende syntaks til at angive en pakke direktiv i kildekode:

'pakke' packageName [ '.' underpakkenavn ... ] ';' 

EN pakke direktivet begynder med pakke nøgleord. En identifikator, der navngiver en pakke, packageName, straks følger. Hvis klasser og grænseflader skal vises i en underpakke (på et niveau) indeni packageName, en eller flere periodeseparerede underpakkenavn identifikatorer vises efter packageName. Følgende kodefragment præsenterer et par pakke direktiver:

pakke spil; pakke-spil-enheder; 

Den første pakke Direktivet identificerer en pakke med navnet spil. Alle klasser og grænseflader, der vises i direktivets kildefil, organiseres i spil pakke. Sekundet pakke Direktivet identificerer en navngivet underpakning enheder, som ligger i en pakke med navnet spil. Alle klasser og grænseflader, der vises i direktivets kildefil, organiseres i spil pakke er enheder underpakke. Hvis en JVM-implementering kortlægger pakkenavne til katalognavne, spilenheder kort til en spil \ enheder kataloghierarki under Windows og a spil / enheder kataloghierarki under Linux eller Solaris.

Advarsel
Kun en pakke direktivet kan vises i en kildefil. Desuden er den pakke direktivet skal være den første kode (bortset fra kommentarer) i filen. Overtrædelse af begge regler får Java's kompilator til at rapportere en fejl.

For at hjælpe dig med at blive fortrolig med pakker har jeg udarbejdet et eksempel, der spænder over alle emner i denne artikel. I dette afsnit lærer du, hvordan du opretter eksemplets pakke. I senere sektioner lærer du, hvordan du importerer en klasse og en grænseflade fra denne pakke, hvordan du flytter denne pakke til et andet sted på din harddisk og stadig får adgang til pakken fra et program, og hvordan du gemmer pakken i en jar-fil . Liste 1 viser pakkens kildekode:

Notering 1. A.java

// A.java-pakke testpkg; offentlig klasse A {int x = 1; offentlig int y = 2; beskyttet int z = 3; int returnx () {return x; } public int returny () {return y; } beskyttet int returnz () {return z; } offentlig grænseflade StartStop {ugyldig start (); ugyldigt stop (); }} klasse B {offentlig statisk tomrum hej () {System.out.println ("hej"); }} 

Liste 1 introducerer kildekoden til din først navngivne pakke. Det pakke testpkg; direktiv navngiver den pakke testpkg. Inden for testpkg er klasser EN og B. Inden for EN er tre feltdeklarationer, tre metodedeklarationer og en indre interface-erklæring. Inden for B er en enkelt metodedeklaration. Hele kildekoden gemmes i A.java fordi EN er en offentlig klasse. Vores opgave: Gør denne kildekode til en pakke, der består af to klasser og en indre grænseflade (eller en mappe, der indeholder tre klassefiler). Følgende Windows-specifikke trin udfører denne opgave:

  1. Åbn et Windows-kommandovindue og sørg for, at du er i c: drevets rodmappe (hovedmappen - repræsenteret af en indledende tilbageslag\) Karakter). For at gøre det skal du skrive c: kommando efterfulgt af cd \ kommando. (Hvis du bruger et andet drev, skal du udskifte det c: med dit valgte drev. Glem ikke at trykke på Enter-tasten, når du har skrevet en kommando.)
  2. Lave en testpkg bibliotek ved at skrive md testpkg. Bemærk: Når du følger denne artikels trin, skal du ikke skrive perioder efter kommandoerne.
  3. Lave testpkg det aktuelle bibliotek ved at skrive cd testpkg.
  4. Brug en editor til at indtaste Listing 1's kildekode og gemme den kode til en A.java fil i testpkg.
  5. Udarbejde A.java ved at skrive javac A.java. Du skal se klassefiler En $ StartStop.-klasse, En klasseog B. klasse vises i testpkg vejviser.

Figur 1 illustrerer trin 3 til 5.

Tillykke! Du har lige oprettet din første pakke. Tænk på denne pakke, som indeholder to klasser (EN og B) og EN's enkelt indre grænseflade (StartStop). Du kan også tænke på denne pakke som en mappe, der indeholder tre klassefiler: En $ StartStop.-klasse, En klasseog B. klasse.

Bemærk
For at minimere konflikter på pakkenavne (især blandt kommercielle pakker) har Sun etableret en konvention, hvor en virksomheds internetdomænenavn vender og foran en pakkenavn. For eksempel et firma med x.com som dets internetdomæne og a.b som et pakkenavn (-en) efterfulgt af et underpakningsnavn (b) præfikser com.x til a.b, resulterende i com.x.a.b. Min artikel følger ikke denne konvention, fordi testpkg pakken er et kast, der kun er beregnet til undervisningsformål.

Importer en pakke klasser og grænseflader

Når du har en pakke, vil du importere klasser og / eller grænseflader - faktisk klasse- og / eller grænsefladenavne - fra den pakke til dit program, så det kan bruge disse klasser og / eller grænseflader. En måde at udføre denne opgave på er at angive det fuldt kvalificerede pakkenavn (pakkenavnet og alle underpakkenavne) hvert sted, hvor referencetypenavnet (klassen eller interface-navnet) vises, som liste 2 viser:

Notering 2. Usetestpkg1.java

// Usetestpkg1.java klasse Usetestpkg1 implementerer 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 = ny Usetestpkg1 (); utp.start (); udp.stop (); } offentlig ugyldig start () {System.out.println ("Start"); } offentligt ugyldigt stop () {System.out.println ("Stop"); }} 

Ved at prefikse testpkg. til EN, Usetestpkg1 adgang testpkg's klasse EN to steder og EN's indre grænseflade StartStop ét sted. Udfør følgende trin for at kompilere og køre Usetestpkg1:

  1. Åbn et Windows-kommandovindue, og sørg for at du er i c: drevets rodmappe.
  2. Sørg for, at klassesti miljøvariabel findes ikke ved at udføre indstil klassesti =. (Jeg diskuterer klassesti senere i denne artikel.)
  3. Brug en editor til at indtaste Listing 2's kildekode og gem den kode til en Usetestpkg1.java fil i rodmappen.
  4. Udarbejde Usetestpkg1.java ved at skrive javac Usetestpkg1.java. Du skal se klassefilen Usetestpkg1.klasse vises i rodmappen.
  5. Type java Usetestpkg1 for at køre dette program.

Figur 2 illustrerer trin 3 til 5 og viser programmets output.

Ifølge Usetestpkg1's output, den hoved () metodens tråd får adgang til testpkg.A's y felt og kalder retur () metode. Desuden viser output en vellykket implementering af testpkg.A.StartStop indre grænseflade.

Til Usetestpkg1, prefixing testpkg. til EN tre steder ser det ikke ud til at være noget stort. Men hvem ønsker at specificere et fuldt kvalificeret pakkenavnspræfiks hundrede steder? Heldigvis leverer Java importere direktiv om at importere en pakkes offentlige referencetypenavn (er), så du ikke behøver at indtaste fuldt kvalificerede pakkenavnspræfikser. Udtryk en importere direktiv i kildekode via følgende syntaks:

'importere' packageName [ '.' underpakkenavn ... ] '.' ( referencetypeName | '*' ) ';' 

En importere direktivet består af importere nøgleord straks efterfulgt af en identifikator, der navngiver en pakke, packageName. En valgfri liste over underpakkenavn identifikatorer følger for at identificere den relevante underpakning (om nødvendigt). Direktivet afsluttes med enten a referencetypeName identifikator, der identificerer en bestemt klasse eller grænseflade fra pakken eller en stjerne (*) Karakter. Hvis referencetypeName vises, er direktivet en enkelt-type importere direktiv. Hvis der vises en stjerne, er direktivet en type-on-demand importere direktiv.

Advarsel
Som med pakke direktiv, importere direktiver skal vises foran enhver anden kode med tre undtagelser: a pakke direktiv, andet importere direktiver eller kommentarer.

Den eneste type importere direktiv importerer navnet på en enkelt offentlig referencetype fra en pakke, som følgende kodefragment viser:

importere java.util.Date; 

Den forrige single-type importere direktiv importerer klasse navn Dato ind i kildekoden. Som et resultat angiver du Dato i stedet for java.util.Date hvert sted vises klassens navn i kildekoden. For eksempel når du opretter en Dato objekt, angiv Dato d = ny Dato (); i stedet for java.util.Date d = ny java.util.Date ();.

Udvis omhu med single-type importere direktiver. Hvis compileren registrerer en enkelt type importere direktiv, der specificerer et referencetypenavn, der også er deklareret i en kildefil, rapporterer compileren en fejl, som følgende kodefragment viser:

importere java.util.Date; klasse Dato {} 

Compileren betragter kodefragmentet som et forsøg på at introducere to referencetyper med det samme Dato navn:

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