Programmering

Pakker og statisk import i Java

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:

  1. Du kan kun erklære én pakkeerklæring i en kildefil.
  2. 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 lagrer Lyd klasse. Denne oppføringen begynner med en pakkeerklæring som identifiserer ca. javajeff.audio som klassens pakke.
  • Lyd blir erklært offentlig slik at det kan henvises til fra utsiden av pakken. Det er også erklært endelig slik at den ikke kan utvides (som betyr, underklassert).
  • Lyd erklærer privatprøver og sampleRate felt for å lagre lyddata. Disse feltene initialiseres til verdiene som sendes til Lydsin konstruktør.
  • Lydsin konstruktør er erklært pakke-privat (som betyr at konstruktøren ikke er erklært offentlig, privat, eller beskyttet) slik at denne klassen ikke kan instantieres fra utsiden av pakken.
  • Lyd gaver getSamples () og getSampleRate () metoder for å returnere et lydklipps prøver og samplingsfrekvens. Hver metode er erklært offentlig slik at det kan kalles utenfra Lydsin pakke.
  • Lyd avsluttes med en offentlig og statisknewAudio () fabrikkmetode for retur av en Lyd objekt som tilsvarer filnavn argument. Hvis lydklippet ikke kan skaffes, null blir returnert.
  • newAudio () sammenligner filnavnutvidelse med .wav (dette eksemplet støtter bare WAV-lyd). Hvis de samsvarer, kjøres det returner WavReader.read (filnavn) å returnere en Lyd 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:

  1. Velg en passende plassering i filsystemet som gjeldende katalog.
  2. Lage en ca / javajeff / lyd underkataloghierarki i gjeldende katalog.
  3. Kopier liste 1 og 2 til filer Audio.java og WavReader.java, henholdsvis; og lagre disse filene i lyd underkatalog.
  4. Forutsatt at den nåværende katalogen inneholder ca. underkatalog, utføre javac ca / ​​javajeff / audio / *. java for å kompilere de to kildefilene i ca / javajeff / lyd. Hvis alt går bra, bør du oppdage det Audio.klasse og WavReader.class filer i lyd underkatalog. (Alternativt, for dette eksemplet, kan du bytte til lyd underkatalog og utføre javac * .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.

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