I min forrige Java 101 opplæring, lærte du hvordan du bedre kan organisere koden din ved å erklære referansetyper (også kjent som klasser og grensesnitt) som medlemmer av andre referansetyper og blokker. Jeg viste deg også hvordan du bruker hekking for å unngå navnekonflikter mellom nestede referansetyper og referansetyper på toppnivå som har samme navn.
Sammen med hekking bruker Java pakker for å løse problemer med samme navn i referansetyper på toppnivå. Bruk av statisk import forenkler også tilgangen til de statiske medlemmene i pakkede referansetyper på toppnivå. Statisk import vil spare deg for tastetrykk når du får tilgang til disse medlemmene i koden din, men det er noen ting du må passe på når du bruker dem. I denne opplæringen vil jeg introdusere deg for bruk av pakker og statisk import i Java-programmene dine.
last ned Få koden Last ned kildekoden for eksempel applikasjoner i denne Java-opplæringen. Skapt av Jeff Friesen for JavaWorld.Emballasjereferansetyper
Java-utviklere grupperer relaterte klasser og grensesnitt i pakker. Ved å bruke pakker blir det lettere å finne og bruke referansetyper, unngå navnekonflikter mellom samme navnetyper og kontrollere tilgang til typer.
I denne delen vil du lære om pakker. Du vil finne ut hva pakkene er, lære om pakke
og import
uttalelser, og utforsk de ekstra emnene med beskyttet tilgang, JAR-filer og typesøk.
Hva er pakker i Java?
I programvareutvikling organiserer vi ofte varer i henhold til deres hierarkiske forhold. I forrige veiledning viste jeg deg hvordan du kan erklære klasser som medlemmer av andre klasser. Vi kan også bruke filsystemer til å hekke kataloger i andre kataloger.
Ved å bruke disse hierarkiske strukturene kan du unngå navnekonflikter. I et ikke-hierarkisk filsystem (en enkelt katalog) er det for eksempel ikke mulig å tilordne det samme navnet til flere filer. Derimot lar et hierarkisk filsystem filene med samme navn eksistere i forskjellige kataloger. På samme måte kan to vedlagte klasser inneholde nestede klasser med samme navn. Navnekonflikter eksisterer ikke fordi elementene er delt inn i forskjellige navneområder.
Java lar oss også partisjonere toppnivå (ikke-nestede) referansetyper i flere navnerom, slik at vi bedre kan organisere disse typene og for å forhindre navnekonflikter. I Java bruker vi pakkespråkfunksjonen til å partisjonere referansetyper på toppnivå i flere navnerom. I dette tilfellet, a pakke er et unikt navneområde for lagring av referansetyper. Pakker kan lagre klasser og grensesnitt, så vel som underpakker, som er pakker nestet i andre pakker.
En pakke har et navn, som må være en ikke-reservert identifikator; for eksempel, java
. Medlemstilgangsoperatøren (.
) skiller et pakkenavn fra et underpakkenavn og skiller et navn på pakken eller underpakken fra et typenavn. For eksempel to-medlem tilgangsoperatører i java.lang.System
eget pakkenavn java
fra lang
underpakkenavn og eget underpakkenavn lang
fra System
skriv navn.
Referansetyper må deklareres offentlig
å være tilgjengelig utenfor pakkene sine. Det samme gjelder konstanter, konstruktører, metoder eller nestede typer som må være tilgjengelige. Du vil se eksempler på disse senere i opplæringen.
Pakkeoppgaven
I Java bruker vi pakkeerklæring for å lage en pakke. Denne setningen vises øverst i en kildefil og identifiserer pakken som kildefiltypene tilhører. Den må stemme overens med følgende syntaks:
pakke identifikator[.identifikator]*;
En pakkeuttalelse starter med det reserverte ordet pakke
og fortsetter med en identifikator, som eventuelt blir fulgt av en periodeseparert sekvens av identifikatorer. Et semikolon (;
) avslutter denne uttalelsen.
Den første (lengst til venstre) identifikatoren gir pakken navn, og hver påfølgende identifikator navngir en underpakke. For eksempel i pakke a.b;
, tilhører alle typer som er angitt i kildefilen b
delpakken til en
pakke.
Navnekonvensjon for pakke / underpakke
Etter konvensjon uttrykker vi et pakke- eller underpakkenavn med små bokstaver. Når navnet består av flere ord, vil du kanskje bruke store bokstaver på hvert ord bortsett fra det første. for eksempel, generalLedger
.
En sekvens av pakkenavn må være unik for å unngå kompileringsproblemer. Anta for eksempel at du oppretter to forskjellige grafikk
pakker, og antar at hver grafikk
pakken inneholder en Triangel
klasse med et annet grensesnitt. Når Java-kompilatoren møter noe som det som er nedenfor, må den verifisere at Trekant (int, int, int, int)
konstruktør eksisterer:
Trekant t = ny Trekant (1, 20, 30, 40);
Trekant avgrensningsboks
Tenk på Triangel
som angir en avgrensningsboks der trekanten skal tegnes. De to første parameterne identifiserer boksens øvre venstre hjørne, og de andre to parameterne definerer boksens omfang.
Kompilatoren vil søke i alle tilgjengelige pakker til den finner en grafikk
pakke som inneholder en Triangel
klasse. Hvis den funnet pakken inneholder det aktuelle Triangel
klasse med en Trekant (int, int, int, int)
konstruktør, alt er bra. Ellers hvis funnet Triangel
klasse har ikke en Trekant (int, int, int, int)
konstruktør, rapporterer kompilatoren en feil. (Jeg vil si mer om søkealgoritmen senere i denne opplæringen.)
Dette scenariet illustrerer viktigheten av å velge unike pakkenavnsekvenser. Konvensjonen med å velge en unik navnesekvens er å reversere internettdomenet og bruke det som et prefiks for sekvensen. For eksempel vil jeg velge ca. javajeff
som prefikset mitt fordi javajeff.ca
er domenenavnet mitt. Jeg vil da spesifisere ca.javajeff.graphics.Triangle
å få tilgang Triangel
.
Domenenavnkomponenter og gyldige pakkenavn
Domenenavnkomponenter er ikke alltid gyldige pakkenavn. Ett eller flere komponentnavn kan starte med et siffer (3D.com
), inneholder bindestrek (-
) eller en annen ulovlig karakter (ab-z.com
), eller være et av Javas reserverte ord (short.com
). Konvensjonen tilsier at du foran sifferet med en understreking (com._3D
), erstatt den ulovlige karakteren med en understreking (com.ab_z
), og suffikset av det reserverte ordet med en understreking (com.short_
).
Du må følge et par regler for å unngå ytterligere problemer med pakkeoppgaven:
- Du kan kun erklære én pakkeerklæring i en kildefil.
- Du kan ikke gå foran pakkseddelen med noe annet enn kommentarer.
Den første regelen, som er et spesielt tilfelle av den andre regelen, eksisterer fordi det ikke gir mening å lagre en referansetype i flere pakker. Selv om en pakke kan lagre flere typer, kan en type kun tilhøre en pakke.
Når en kildefil ikke erklærer en pakkeerklæring, sies kildefilens typer å tilhøre unavngitt pakke. Ikke-trivielle referansetyper lagres vanligvis i egne pakker og unngår den navnløse pakken.
Java-implementeringer tilordner pakkenavn og underpakkenavn til samme navn kataloger. For eksempel vil en implementering kartlegge grafikk
til en katalog som heter grafikk
. I tilfelle av pakken a.b
, første bokstav, en ville kartlagt til en katalog som heter en
og b ville kartlagt til en b
underkatalog til en
. Kompilatoren lagrer klassefilene som implementerer pakkens typer i den tilsvarende katalogen. Merk at den ikke-navngitte pakken tilsvarer den gjeldende katalogen.
Eksempel: Pakke et lydbibliotek i Java
Et praktisk eksempel er nyttig for full forståelse av pakke
uttalelse. I denne delen demonstrerer jeg pakker i sammenheng med et lydbibliotek som lar deg lese lydfiler og få lyddata. For kortfattethet vil jeg bare presentere en skjelettversjon av biblioteket.
Lydbiblioteket består for tiden bare av to klasser: Lyd
og WavReader
. Lyd
beskriver et lydklipp og er bibliotekets hovedklasse. Oppføring 1 presenterer kildekoden.
Oppføring 1. Eksempel på pakkeuttalelse (Audio.java)
pakke ca. javajeff.audio; offentlig sluttklasse Audio {private int [] prøver; private int sampleRate; Audio (int [] samples, int sampleRate) {this.samples = samples; this.sampleRate = sampleRate; } public int [] getSamples () {return samples; } public int getSampleRate () {return sampleRate; } offentlig statisk lyd newAudio (strengfilnavn) {hvis (filnavn.tilLowerCase (). slutter med (". wav")) returnerer WavReader.read (filnavn); ellers returnere null; // ikke støttet format } }
La oss gå gjennom Listing 1 trinn for trinn.
- De
Audio.java
filen i Listing 1 lagrerLyd
klasse. Denne oppføringen begynner med en pakkeerklæring som identifisererca. javajeff.audio
som klassens pakke. Lyd
blir erklærtoffentlig
slik at det kan henvises til fra utsiden av pakken. Det er også erklærtendelig
slik at den ikke kan utvides (som betyr, underklassert).Lyd
erklærerprivat
prøver
ogsampleRate
felt for å lagre lyddata. Disse feltene initialiseres til verdiene som sendes tilLyd
sin konstruktør.Lyd
sin konstruktør er erklært pakke-privat (som betyr at konstruktøren ikke er erklærtoffentlig
,privat
, ellerbeskyttet
) slik at denne klassen ikke kan instantieres fra utsiden av pakken.Lyd
gavergetSamples ()
oggetSampleRate ()
metoder for å returnere et lydklipps prøver og samplingsfrekvens. Hver metode er erklærtoffentlig
slik at det kan kalles utenfraLyd
sin pakke.Lyd
avsluttes med enoffentlig
ogstatisk
newAudio ()
fabrikkmetode for retur av enLyd
objekt som tilsvarerfilnavn
argument. Hvis lydklippet ikke kan skaffes,null
blir returnert.newAudio ()
sammenlignerfilnavn
utvidelse med.wav
(dette eksemplet støtter bare WAV-lyd). Hvis de samsvarer, kjøres detreturner WavReader.read (filnavn)
å returnere enLyd
objekt med WAV-baserte lyddata.
Oppføring 2 beskriver WavReader
.
Oppføring 2. WavReader-hjelperklassen (WavReader.java)
pakke ca. javajeff.audio; final class WavReader {static Audio read (Strengfilnavn) {// Les innholdet i filnavnet og behandle det // til en rekke eksempler på verdier og en samplingsfrekvens // verdi. Hvis filen ikke kan leses, returner null. For // korthet (og fordi jeg ennå ikke har diskutert Java // fil I / O APIer), presenterer jeg bare skjelettkode som // alltid returnerer et lydobjekt med standardverdier. returner ny lyd (ny int [0], 0); }}
WavReader
er ment å lese innholdet i en WAV-fil inn i en Lyd
gjenstand. (Klassen vil etter hvert bli større med tillegg privat
felt og metoder.) Legg merke til at denne klassen ikke er deklarert offentlig
, som gjør WavReader
tilgjengelig for Lyd
men ikke å kode utenfor ca. javajeff.audio
pakke. Tenker på WavReader
som en hjelperklasse hvis eneste grunn til eksistens er å tjene Lyd
.
Fullfør følgende trinn for å bygge dette biblioteket:
- Velg en passende plassering i filsystemet som gjeldende katalog.
- Lage en
ca / javajeff / lyd
underkataloghierarki i gjeldende katalog. - Kopier liste 1 og 2 til filer
Audio.java
ogWavReader.java
, henholdsvis; og lagre disse filene ilyd
underkatalog. - Forutsatt at den nåværende katalogen inneholder
ca.
underkatalog, utførejavac ca / javajeff / audio / *. java
for å kompilere de to kildefilene ica / javajeff / lyd
. Hvis alt går bra, bør du oppdage detAudio.klasse
ogWavReader.class
filer ilyd
underkatalog. (Alternativt, for dette eksemplet, kan du bytte tillyd
underkatalog og utførejavac * .java
.)
Nå som du har opprettet lydbiblioteket, vil du bruke det. Snart skal vi se på et lite Java-program som demonstrerer dette biblioteket. Først må du lære om importoppgaven.
Java's importerklæring
Tenk deg å måtte spesifisere ca.javajeff.graphics.Triangle
for hver forekomst av Triangel
i kildekoden, gjentatte ganger. Java gir importoppgaven som et praktisk alternativ for å utelate lange pakkeopplysninger.
Importoppgaven importerer typer fra en pakke ved å fortelle kompilatoren hvor du skal se etter ukvalifisert (ingen pakkeprefiks) skriv navn under kompilering. Den vises nær toppen av en kildefil og må stemme overens med følgende syntaks:
import identifikator[.identifikator]*.(typenavn | *);
En importerklæring starter med reservert ord import
og fortsetter med en identifikator, som eventuelt blir fulgt av en periodeseparert sekvens av identifikatorer. Et typenavn eller stjerne (*
) følger, og et semikolon avslutter denne påstanden.
Syntaksen avslører to former for importuttalelsen. Først kan du importere et enkelt navn, som identifiseres via typenavn
. For det andre kan du importere alle typer, som identifiseres via stjernen.
De *
symbol er et jokertegn som representerer alle ukvalifiserte typenavn. Den forteller kompilatoren å lete etter slike navn i pakken til høyre for importuttalelsens pakkesekvens med mindre typenavnet er funnet i en tidligere søkt pakke. Merk at bruk av jokertegn ikke har noen ytelsesstraff eller fører til oppblåst kode. Det kan imidlertid føre til navnekonflikter, som du vil se.
For eksempel, importer ca.javajeff.graphics.Triangle;
forteller kompilatoren at en ukvalifisert Triangel
klasse eksisterer i ca. javajeff. grafikk
pakke. Tilsvarende noe sånt
importer ca.javajeff.graphics. *;
ber kompilatoren se i denne pakken når den møter a Triangel
navn, a Sirkel
navn, eller til og med et Regnskap
navn (hvis Regnskap
har ikke allerede blitt funnet).
Unngå * i flerutviklerprosjekter
Når du jobber med et flerutviklerprosjekt, unngå å bruke *
jokertegn slik at andre utviklere enkelt kan se hvilke typer som brukes i kildekoden din.