I min forrige Java 101 tutorial lærte du, hvordan du bedre organiserer din kode ved at erklære referencetyper (også kendt som klasser og grænseflader) som medlemmer af andre referencetyper og -blokke. Jeg viste dig også, hvordan du bruger indlejring for at undgå navnekonflikter mellem indlejrede referencetyper og referencetyper på øverste niveau, der har samme navn.
Sammen med indlejring bruger Java pakker til at løse problemer med samme navn i referencetyper på øverste niveau. Brug af statisk import forenkler også adgangen til de statiske medlemmer i pakkede topniveau referencetyper. Statisk import gemmer dig tastetryk, når du får adgang til disse medlemmer i din kode, men der er et par ting at passe på, når du bruger dem. I denne vejledning vil jeg introducere dig til at bruge pakker og statisk import i dine Java-programmer.
download Hent koden Download kildekoden for eksempel applikationer i denne Java-tutorial. Oprettet af Jeff Friesen til JavaWorld.Emballagereferenstyper
Java-udviklere grupperer relaterede klasser og grænseflader i pakker. Brug af pakker gør det lettere at lokalisere og bruge referencetyper, undgå navnekonflikter mellem samme navngivne typer og kontrollere adgang til typer.
I dette afsnit lærer du om pakker. Du finder ud af, hvad pakker er, lær om pakke
og importere
erklæringer og udforske de ekstra emner beskyttet adgang, JAR-filer og typesøgninger.
Hvad er pakker i Java?
I softwareudvikling organiserer vi ofte varer i henhold til deres hierarkiske forhold. For eksempel viste jeg i den foregående vejledning, hvordan man erklærer klasser som medlemmer af andre klasser. Vi kan også bruge filsystemer til at indlejre mapper i andre mapper.
Brug af disse hierarkiske strukturer hjælper dig med at undgå navnekonflikter. For eksempel er det i et ikke-hierarkisk filsystem (en enkelt mappe) ikke muligt at tildele det samme navn til flere filer. I modsætning hertil lader et hierarkisk filsystem filer med samme navn eksistere i forskellige kataloger. Tilsvarende kan to omsluttende klasser indeholde samme navngivne indlejrede klasser. Navnekonflikter findes ikke, fordi emner er opdelt i forskellige navneområder.
Java giver os også mulighed for at opdele referencetyper på topniveau (ikke-indlejrede) i flere navneområder, så vi bedre kan organisere disse typer og forhindre navnekonflikter. I Java bruger vi pakkens sprogfunktion til at opdele referencetyper på øverste niveau i flere navneområder. I dette tilfælde a pakke er et unikt navneområde til lagring af referencetyper. Pakker kan gemme klasser og grænseflader samt underpakker, hvilke pakker er indlejret i andre pakker.
En pakke har et navn, som skal være en ikke-reserveret identifikator; for eksempel, java
. Medlemadgangsoperatøren (.
) adskiller et pakkenavn fra et underpakkenavn og adskiller et pakke- eller underpakningsnavn fra et typenavn. For eksempel er to-medlems adgangsoperatører i java.lang.System
separat pakke navn java
fra lang
underpakke navn og separat underpakke navn lang
fra System
skriv navn.
Referencetyper skal erklæres offentlig
at være tilgængelig uden for deres pakker. Det samme gælder for konstanter, konstruktører, metoder eller indlejrede typer, der skal være tilgængelige. Du kan se eksempler på disse senere i vejledningen.
Pakkeerklæringen
I Java bruger vi pakkeerklæring at oprette en pakke. Denne erklæring vises øverst i en kildefil og identificerer den pakke, som kildefiltyperne hører til. Den skal svare til følgende syntaks:
pakke identifikator[.identifikator]*;
En pakkeerklæring starter med det reserverede ord pakke
og fortsætter med en identifikator, der eventuelt efterfølges af en periodesepareret sekvens af identifikatorer. Et semikolon (;
) opsiger denne erklæring.
Den første (længst til venstre) identifikator navngiver pakken, og hver efterfølgende identifikator navngiver en underpakke. For eksempel i pakke a.b;
, alle typer, der er angivet i kildefilen, hører til b
underpakning af -en
pakke.
Pakke / underpakning navngivningskonvention
Efter konvention udtrykker vi et pakke- eller underpakningsnavn med små bogstaver. Når navnet består af flere ord, vil du muligvis bruge et stort stort bogstav med undtagelse af det første. for eksempel, generalLedger
.
En sekvens af pakkenavne skal være unik for at undgå kompileringsproblemer. Antag for eksempel, at du opretter to forskellige grafik
pakker, og antag, at hver grafik
pakken indeholder en Trekant
klasse med en anden grænseflade. Når Java-kompileren støder på noget som det nedenfor, skal det bekræfte, at Trekant (int, int, int, int)
konstruktør eksisterer:
Trekant t = ny Trekant (1, 20, 30, 40);
Trekantsafgrænsningsboks
Tænk på Trekant
konstruktør som angiver en afgrænsningsboks, hvor trekanten skal tegnes. De to første parametre identificerer feltets øverste venstre hjørne, og de to andre parametre definerer feltets omfang.
Compileren søger i alle tilgængelige pakker, indtil den finder en grafik
pakke, der indeholder en Trekant
klasse. Hvis den fundne pakke indeholder det relevante Trekant
klasse med en Trekant (int, int, int, int)
konstruktør, alt er i orden. Ellers hvis fundet Trekant
klasse har ikke en Trekant (int, int, int, int)
konstruktør, rapporterer compileren en fejl. (Jeg siger mere om søgealgoritmen senere i denne vejledning.)
Dette scenario illustrerer vigtigheden af at vælge unikke sekvenser for pakkenavn. Konventionen ved valg af en unik navnesekvens er at vende dit internetdomænenavn og bruge det som et præfiks for sekvensen. For eksempel ville jeg vælge ca. javajeff
som mit præfiks fordi javajeff.ca
er mit domænenavn. Jeg ville derefter specificere ca.javajeff.graphics.Triangle
adgang Trekant
.
Komponenter for domænenavne og gyldige pakkenavne
Komponenter for domænenavne er ikke altid gyldige pakkenavne. Et eller flere komponentnavne starter muligvis med et ciffer (3D.com
), indeholder en bindestreg (-
) eller en anden ulovlig karakter (ab-z.com
), eller være et af Java's reserverede ord (short.com
). Konventionen dikterer, at du præfikser cifferet med en understregning (com._3D
), udskift den ulovlige karakter med en understregning (com.ab_z
), og efterfølger det reserverede ord med en understregning (com.short_
).
Du skal følge et par regler for at undgå yderligere problemer med pakkeerklæringen:
- Du kan kun erklære én pakkeerklæring i en kildefil.
- Du kan ikke gå foran pakkeerklæringen med noget bortset fra kommentarer.
Den første regel, som er et specielt tilfælde af den anden regel, findes, fordi det ikke giver mening at gemme en referencetype i flere pakker. Selvom en pakke kan gemme flere typer, kan en type kun tilhøre en pakke.
Når en kildefil ikke erklærer en pakkeerklæring, siges kildefilens typer at høre til unavngiven pakke. Ikke-trivielle referencetyper gemmes typisk i deres egne pakker og undgår den ikke-navngivne pakke.
Java-implementeringer kortlægger pakke- og underpakkenavne til samme navngivne mapper. For eksempel vil en implementering kortlægge grafik
til en mappe med navnet grafik
. I tilfælde af pakken a.b
, det første bogstav, -en vil kortlægge til et navngivet katalog -en
og b ville kortlægge til en b
underkatalog til -en
. Compileren gemmer de klassefiler, der implementerer pakkens typer i den tilsvarende mappe. Bemærk, at den ikke-navngivne pakke svarer til den aktuelle mappe.
Eksempel: Pakning af et lydbibliotek i Java
Et praktisk eksempel er nyttigt til fuldt ud at forstå pakke
udmelding. I dette afsnit demonstrerer jeg pakker i sammenhæng med et lydbibliotek, der lader dig læse lydfiler og hente lyddata. For kortfattethed præsenterer jeg kun en skeletversion af biblioteket.
Lydbiblioteket består i øjeblikket kun af to klasser: Lyd
og WavReader
. Lyd
beskriver et lydklip og er bibliotekets hovedklasse. Liste 1 viser kildekoden.
Liste 1. Eksempel på pakkeerklæring (Audio.java)
pakke ca. javajeff.audio; offentlig endelig klasse Audio {private int [] prøver; privat int sampleRate; Audio (int [] samples, int sampleRate) {this.samples = samples; this.sampleRate = sampleRate; } public int [] getSamples () {return samples; } public int getSampleRate () {returner sampleRate; } offentlig statisk lyd newAudio (String-filnavn) {hvis (filnavn.tilLowerCase (). slutter med (". wav")) returnerer WavReader.read (filnavn); ellers returnere null; // ikke-understøttet format}}
Lad os gennemgå Listing 1 trin for trin.
- Det
Audio.java
i Listing 1 gemmerLyd
klasse. Denne fortegnelse begynder med en pakkeerklæring, der identificererca. javajeff.audio
som klassens pakke. Lyd
erklæresoffentlig
så det kan henvises til uden for pakken. Det er også erklæretendelig
så det ikke kan udvides (betyder, underklasseret).Lyd
erklærerprivat
prøver
ogsampleRate
felter til lagring af lyddata. Disse felter initialiseres til de værdier, der sendes tilLyd
s konstruktør.Lyd
konstruktør erklæres pakke-privat (hvilket betyder, konstruktøren er ikke erklæretoffentlig
,privat
, ellerbeskyttet
), så denne klasse ikke kan instantieres uden for pakken.Lyd
præsenterergetSamples ()
oggetSampleRate ()
metoder til returnering af et lydklips prøver og samplingsfrekvens. Hver metode erklæresoffentlig
så det kan kaldes udefraLyd
's pakke.Lyd
afsluttes med enoffentlig
ogstatisk
newAudio ()
fabriksmetode til returnering af enLyd
objekt svarende tilfilnavn
argument. Hvis lydklippet ikke kan opnås,nul
returneres.newAudio ()
sammenlignerfilnavn
udvidelse med.wav
(dette eksempel understøtter kun WAV-lyd). Hvis de matcher, udføres detreturner WavReader.read (filnavn)
at returnere enLyd
objekt med WAV-baserede lyddata.
Liste 2 beskriver WavReader
.
Liste 2. WavReader hjælperklassen (WavReader.java)
pakke ca. javajeff.audio; final class WavReader {statisk lydlæsning (strengfilnavn) {// Læs indholdet af filnavnet og behandl det // til en matrix af prøveværdier og en prøvehastighed // værdi. Hvis filen ikke kan læses, skal du returnere null. For // kortfattethed (og fordi jeg endnu ikke har diskuteret Javas // fil I / O API'er), præsenterer jeg kun skeletkode, der // altid returnerer et lydobjekt med standardværdier. returner ny lyd (ny int [0], 0); }}
WavReader
er beregnet til at læse en WAV-fils indhold i en Lyd
objekt. (Klassen bliver til sidst større med yderligere privat
felter og metoder.) Bemærk, at denne klasse ikke er erklæret offentlig
, hvilket gør WavReader
tilgængelig for Lyd
men ikke at kode uden for ca. javajeff.audio
pakke. Tænke på WavReader
som en hjælperklasse, hvis eneste grund til eksistens er at tjene Lyd
.
Udfør følgende trin for at opbygge dette bibliotek:
- Vælg en passende placering i dit filsystem som det aktuelle bibliotek.
- Lave en
ca / javajeff / lyd
underkataloghierarki i den aktuelle mappe. - Kopier lister 1 og 2 til filer
Audio.java
ogWavReader.java
, henholdsvis; og gem disse filer ilyd
underkatalog. - Forudsat at den aktuelle mappe indeholder
ca.
underkatalog, udførjavac ca / javajeff / audio / *. java
for at kompilere de to kildefiler ica / javajeff / lyd
. Hvis alt går godt, skal du opdageAudio.class
ogWavReader.class
filer ilyd
underkatalog. (Alternativt kan du i dette eksempel skifte tillyd
underkatalog og udførejavac * .java
.)
Nu hvor du har oprettet lydbiblioteket, vil du gerne bruge det. Snart ser vi på et lille Java-program, der demonstrerer dette bibliotek. Først skal du lære om importerklæringen.
Java's importerklæring
Forestil dig at skulle specificere ca.javajeff.graphics.Triangle
for hver forekomst af Trekant
i kildekoden gentagne gange. Java leverer importopgørelsen som et praktisk alternativ til udeladelse af lange pakkeoplysninger.
Importopgørelsen importerer typer fra en pakke ved at fortælle kompilatoren, hvor den skal søges ukvalificeret (intet pakkepræfiks) skrivnavne under kompilering. Det vises nær toppen af en kildefil og skal svare til følgende syntaks:
importere identifikator[.identifikator]*.(type Navn | *);
En importerklæring starter med reserveret ord importere
og fortsætter med en identifikator, der eventuelt efterfølges af en periodesepareret sekvens af identifikatorer. Et typenavn eller en stjerne (*
) følger, og et semikolon afslutter denne erklæring.
Syntaksen afslører to former for importopgørelsen. For det første kan du importere et enkelt navn, som identificeres via type Navn
. For det andet kan du importere alle typer, som identificeres via stjernen.
Det *
symbol er et jokertegn, der repræsenterer alle ukvalificerede typenavne. Det fortæller kompilatoren at kigge efter sådanne navne i den yderste pakke i importopgørelsens pakkesekvens, medmindre typenavnet findes i en tidligere søgt pakke. Bemærk, at brug af jokertegnet ikke har en præstationsstraff eller fører til opblødning af kode. Det kan dog føre til navnekonflikter, som du vil se.
For eksempel, import ca. javajeff.graphics.Triangle;
fortæller kompilatoren, at en ukvalificeret Trekant
klasse findes i ca. javajeff. grafik
pakke. Tilsvarende noget lignende
import ca.javajeff.graphics. *;
fortæller kompilatoren at se i denne pakke, når den møder en Trekant
navn, a Cirkel
navn eller endda et Konto
navn (hvis Konto
er ikke allerede fundet).
Undgå * i multi-udvikler projekter
Når du arbejder på et multi-udvikler-projekt, skal du undgå at bruge *
wildcard, så andre udviklere nemt kan se, hvilke typer der bruges i din kildekode.