Programavimas

Paketai ir statinis importas „Java“

Mano ankstesniame „Java 101“ pamoka, jūs sužinojote, kaip geriau tvarkyti kodą, deklaruodami nuorodų tipus (dar vadinamus klasėmis ir sąsajomis) kitų nuorodų tipų ir blokų nariais. Aš taip pat parodžiau, kaip naudoti lizdą, kad būtų išvengta vardų konfliktų tarp įdėtų nuorodų tipų ir aukščiausio lygio nuorodų tipų, kurie turi tą patį pavadinimą.

Kartu su lizdu „Java“ naudoja paketus, kad išspręstų to paties pavadinimo problemas aukščiausio lygio nuorodų tipuose. Statinio importavimo naudojimas taip pat supaprastina prieigą prie statinių narių supakuotuose aukščiausio lygio nuorodų tipuose. Statinis importavimas sutaupys klavišų paspaudimus, kai prieisite prie šių savo kodo narių, tačiau juos naudojant reikia atkreipti dėmesį į keletą dalykų. Šioje pamokoje aš supažindinsiu jus su paketų naudojimu ir statiniu importavimu savo „Java“ programose.

atsisiųsti Gauti kodą Atsisiųskite šaltinių kodą, pvz., programas, šioje „Java“ mokymo programoje. Sukūrė Jeffas Friesenas, skirtas „JavaWorld“.

Pakuotės nuorodų tipai

„Java“ kūrėjai grupuoja susijusias klases ir sąsajas į paketus. Naudojant paketus lengviau rasti ir naudoti nuorodų tipus, išvengti vardų konfliktų tarp tų pačių pavadinimų tipų ir kontroliuoti prieigą prie tipų.

Šiame skyriuje sužinosite apie paketus. Sužinosite, kokie yra paketai, sužinosite apie pakuotė ir importas sakinius ir nagrinėkite papildomas apsaugotos prieigos, JAR failų ir tipų paieškų temas.

Kas yra „Java“ paketai?

Kurdami programinę įrangą, mes paprastai organizuojame elementus pagal jų hierarchinius santykius. Pavyzdžiui, ankstesnėje pamokoje aš jums parodžiau, kaip deklaruoti klases kaip kitų klasių narius. Mes taip pat galime naudoti failų sistemas, kad įdėtume katalogus į kitus katalogus.

Naudodami šias hierarchines struktūras galėsite išvengti vardų konfliktų. Pavyzdžiui, ne hierarchinėje failų sistemoje (viename kataloge) neįmanoma to paties pavadinimo priskirti keliems failams. Priešingai, hierarchinė failų sistema leidžia tų pačių pavadinimų failus egzistuoti skirtinguose kataloguose. Panašiai dviejose uždarosiose klasėse gali būti to paties pavadinimo įdėtos klasės. Vardų konfliktų nėra, nes elementai yra suskirstyti į skirtingas vardų sritis.

„Java“ taip pat leidžia mums suskirstyti aukščiausio lygio (ne įdėtus) nuorodų tipus į kelias vardų sritis, kad galėtume geriau sutvarkyti šiuos tipus ir užkirsti kelią vardų konfliktams. „Java“ paketo kalbos funkciją naudojame viršutinio lygio nuorodų tipų skaidymui į kelias vardų sritis. Šiuo atveju a pakuotė yra unikali vardų sritis, skirta saugoti nuorodų tipus. Paketai gali laikyti klases ir sąsajas, taip pat paketai, kurios yra pakuotės, įdėtos į kitas pakuotes.

Paketas turi pavadinimą, kuris turi būti nerezervuotas identifikatorius; pavyzdžiui, java. Narių prieigos operatorius (.) atskiria paketo pavadinimą nuo paketo pavadinimo ir atskiria paketo ar paketo pavadinimą nuo tipo pavadinimo. Pavyzdžiui, dviejų narių prieigos operatoriai java.lang.Sistema atskiras paketo pavadinimas java nuo lang pakuotės pavadinimas ir atskiras pakuotės pavadinimas lang nuo Sistema tipo pavadinimas.

Turi būti deklaruojami pagrindiniai tipai visuomenės kad būtų galima patekti iš jų pakuočių išorės. Tas pats pasakytina apie visas konstantas, konstruktorius, metodus ar įdėtus tipus, kurie turi būti prieinami. Šių pavyzdžių pamatysite vėliau pamokoje.

Paketo išrašas

„Java“ mes naudojame paketo išrašas sukurti paketą. Šis sakinys rodomas šaltinio failo viršuje ir identifikuoja paketą, kuriam priklauso šaltinio failų tipai. Ji turi atitikti šią sintaksę:

 pakuotė identifikatorius[.identifikatorius]*; 

Paketo sakinys prasideda rezervuotu žodžiu pakuotė ir tęsiama identifikatoriumi, po kurio pasirinktinai seka taškų atskirtoji identifikatorių seka. Kabliataškis (;) nutraukia šį teiginį.

Pirmasis (kairysis kairysis) identifikatorius pavadina paketą, o kiekvienas paskesnis identifikatorius - paketą. Pavyzdžiui, paketas a.b;, visi šaltinio faile deklaruoti tipai priklauso b subpakuotė a pakuotė.

Pakuočių / pakuočių pavadinimų suteikimo tvarka

Pagal susitarimą pakuotės ar pakuotės pavadinimą išreiškiame mažosiomis raidėmis. Kai vardą sudaro keli žodžiai, kiekvieną žodį galite rašyti didžiąja raide, išskyrus pirmąjį; pavyzdžiui, didžioji knyga.

Paketų pavadinimų seka turi būti unikali, kad būtų išvengta kompiliavimo problemų. Pavyzdžiui, tarkime, kad sukūrėte du skirtingus grafika paketus, ir manykite, kad kiekvienas grafika pakuotėje yra a Trikampis klasės su kita sąsaja. Kai „Java“ kompiliatorius susiduria su kažkuo panašiu į tai, kas yra žemiau, jis turi patikrinti, ar Trikampis (int, int, int, int) konstruktorius egzistuoja:

 Trikampis t = naujas trikampis (1, 20, 30, 40); 

Trikampį ribojanti dėžutė

Pagalvokite apie Trikampis konstruktorius kaip nurodantis ribojančią dėžę, kurioje nupiešiamas trikampis. Pirmieji du parametrai nurodo langelio viršutinį kairįjį kampą, o antrieji du parametrai nurodo langelio apimtį.

Kompiliatorius ieškos visų prieinamų paketų, kol ras grafika pakuotė, kurioje yra a Trikampis klasė. Jei rastame pakete yra atitinkama Trikampis klasė su a Trikampis (int, int, int, int) konstruktorius, viskas gerai. Priešingu atveju, jei rasta Trikampis klasėje nėra a Trikampis (int, int, int, int) konstruktorius, kompiliatorius praneša apie klaidą. (Apie paieškos algoritmą pasakysiu vėliau šioje pamokoje.)

Šis scenarijus parodo, kaip svarbu pasirinkti unikalias paketų pavadinimų sekas. Pasirenkant unikalią vardų seką įprasta pakeisti savo interneto domeno vardą ir naudoti jį kaip sekos priešdėlį. Pavyzdžiui, aš rinkčiausi ca.javajeffas kaip mano priešdėlis, nes javajeff.ca yra mano domeno vardas. Tada patikslinčiau ca.javajeff.graphics.Triangle prieiti Trikampis.

Domeno vardo komponentai ir galiojantys paketų pavadinimai

Domeno vardo komponentai ne visada yra tinkami paketų pavadinimai. Vienas ar daugiau komponentų pavadinimų gali prasidėti skaitmeniu (3D.com), turi brūkšnį (-) ar kito neteisėto pobūdžio asmens (ab-z.com) arba būti vienas iš „Java“ rezervuotų žodžių (short.com). „Convention“ nurodo, kad prieš skaitmenį prieš pabraukdami (com._3D), neteisėtą simbolį pakeiskite pabraukimu (com.ab_z) ir pridėkite rezervuotą žodį pabraukimu (com.trumpa_).

Turite laikytis kelių taisyklių, kad išvengtumėte papildomų problemų dėl paketo išrašo:

  1. Šaltinio faile galite deklaruoti tik vieną paketo pareiškimą.
  2. Negalite prieš paketo pareiškimą rašyti nieko, išskyrus komentarus.

Pirmoji taisyklė, kuri yra specialus antrosios taisyklės atvejis, egzistuoja, nes nėra prasmės laikyti nuorodos tipą keliuose paketuose. Nors pakuotėje gali būti saugomi keli tipai, tipas gali priklausyti tik vienam paketui.

Kai šaltinio failas nedeklaruoja paketo sakinio, sakoma, kad šaltinio failo tipai priklauso neįvardinta pakuotė. Netrivialūs nuorodų tipai paprastai laikomi atskirose pakuotėse ir vengia neįvardyto paketo.

„Java“ diegimai paketų ir paketų pavadinimus susieja su tų pačių pavadinimų katalogais. Pavyzdžiui, įgyvendinimas atvaizduotų grafika į katalogą pavadinimu grafika. Pakuotės atveju a.b, pirmoji raidė, a susieti su katalogu, pavadintu a ir b atvaizduotų a b pakatalogis a. Kompiliatorius saugo klasės failus, kurie įgyvendina paketo tipus, atitinkamame kataloge. Atkreipkite dėmesį, kad neįvardytas paketas atitinka dabartinį katalogą.

Pavyzdys: Garso bibliotekos pakavimas į „Java“

Praktinis pavyzdys yra naudingas norint visiškai suvokti pakuotė pareiškimas. Šiame skyriuje demonstruoju paketus garso bibliotekos kontekste, leidžiančiame skaityti garso failus ir gauti garso duomenis. Dėl trumpumo pateiksiu tik karkasinę bibliotekos versiją.

Šiuo metu garso biblioteką sudaro tik dvi klasės: Garsas ir „WavReader“. Garsas apibūdina garso įrašą ir yra pagrindinė bibliotekos klasė. 1 sąraše pateikiamas jo šaltinio kodas.

Sąrašas 1. Paketo išrašo pavyzdys (Audio.java)

 paketas ca.javajeff.audio; public final class Audio {private int [] pavyzdžiai; private int sampleRate; Garso įrašas (int [] pavyzdžiai, int sampleRate) {this.samples = pavyzdžiai; this.sampleRate = sampleRate; } public int [] getSamples () {grąžinti pavyzdžius; } public int getSampleRate () {return sampleRate; } public static Audio newAudio (String filename) {if (filename.toLowerCase (). endWith (". wav")) grąžinti WavReader.read (failo vardas); else return null; // nepalaikomas formatas}} 

Peržiūrėkime 1 sąrašą po žingsnio.

  • Audio.java 1 sąrašo failas saugo Garsas klasė. Šis sąrašas prasideda paketo sakiniu, kuris identifikuoja ca.javajeff.audio kaip klasės paketas.
  • Garsas yra deklaruojamas visuomenės kad į jį būtų galima kreiptis iš jo pakuotės ribų. Be to, tai deklaruota galutinis kad jo nebūtų galima išplėsti (turint omenyje subklasę).
  • Garsas pareiškia privatuspavyzdžiai ir sampleRate laukai garso duomenims saugoti. Šie laukai inicijuojami pagal perduotas vertes Garsaskonstruktorius.
  • Garsasdeklaruojamas konstruktorius paketas-privatus (tai reiškia, kad konstruktorius nėra deklaruojamas visuomenės, privatusarba saugomi), kad šios klasės nebūtų galima nustatyti tiesiai iš jos paketo ribų.
  • Garsas dovanos „getSamples“ () ir getSampleRate () garso įrašo pavyzdžių grąžinimo būdai ir atrankos dažnis. Kiekvienas metodas yra deklaruojamas visuomenės kad jį būtų galima iškviesti iš išorės Garsaspaketą.
  • Garsas baigia a visuomenės ir statinisnewAudio () gamyklos metodas grąžinti Garsas objektas, atitinkantis failo pavadinimas argumentas. Jei garso įrašo nepavyksta gauti, niekinis yra grąžinamas.
  • newAudio () lygina failo pavadinimaspratęsimas su .wav (šis pavyzdys palaiko tik WAV garsą). Jei jie sutampa, jis vykdomas grąžinti WavReader.read (failo pavadinimas) grąžinti Garsas objektas su WAV pagrįstais garso duomenimis.

2 sąraše aprašoma „WavReader“.

2 sąrašas. „WavReader“ pagalbininkų klasė (WavReader.java)

 paketas ca.javajeff.audio; final class WavReader {static Audio read (String filename) {// Perskaitykite failo pavadinimo failo turinį ir apdorokite jį // į pavyzdžių reikšmių masyvą ir mėginių dažnio // reikšmę. Jei failo nuskaityti negalima, grąžinkite nulį. Dėl // trumpumo (ir kadangi aš dar neaptariau „Java“ // failų įvesties / išvesties API), pateikiu tik griaučių kodą, kuris // visada pateikia garso objektą su numatytosiomis reikšmėmis. grąžinti naują garso įrašą (naujas int [0], 0); }} 

„WavReader“ skirtas skaityti WAV failo turinį į Garsas objektas. (Galiausiai klasė bus didesnė su papildomais privatus laukai ir metodai.) Atkreipkite dėmesį, kad ši klasė nėra deklaruota visuomenės, kuris padaro „WavReader“ prieinama Garsas bet ne koduoti už ca.javajeff.audio pakuotė. Galvoti apie „WavReader“ kaip pagalbininkų klasė, kurios vienintelė egzistavimo priežastis yra tarnauti Garsas.

Norėdami sukurti šią biblioteką, atlikite šiuos veiksmus:

  1. Pasirinkite tinkamą failų sistemos vietą kaip dabartinį katalogą.
  2. Sukurti ca / javajeff / audio pakatalogių hierarchija dabartiniame kataloge.
  3. Nukopijuokite 1 ir 2 sąrašus į failus Audio.java ir WavReader.javaatitinkamai; ir išsaugokite šiuos failus garso pakatalogis.
  4. Darant prielaidą, kad dabartiniame kataloge yra apie pakatalogį, vykdyti javac ca / ​​javajeff / audio / *. java surinkti du šaltinio failus į ca / javajeff / audio. Jei viskas gerai, turėtumėte atrasti Garso.klasė ir „WavReader.class“ failus garso pakatalogis. (Arba šiame pavyzdyje galite pereiti prie garso pakatalogį ir vykdyti javac * .java.)

Dabar, sukūrę garso biblioteką, norėsite ja naudotis. Netrukus pažvelgsime į mažą „Java“ programą, kuri demonstruoja šią biblioteką. Pirmiausia turite sužinoti apie importo ataskaitą.

„Java“ importo ataskaita

Įsivaizduokite, kad turite nurodyti ca.javajeff.graphics.Triangle kiekvienam įvykiui Trikampis šaltinio kode, pakartotinai. „Java“ pateikia importo ataskaitą kaip patogią alternatyvą praleisti ilgą paketo informaciją.

Importo pareiškime importuojami tipai iš paketo nurodant kompiliatoriui, kur ieškoti nekvalifikuotas (be paketo priešdėlio) tipo pavadinimai kompiliavimo metu. Jis rodomas šalia šaltinio failo viršaus ir turi atitikti šią sintaksę:

 importas identifikatorius[.identifikatorius]*.(typeName | *); 

Importavimo ataskaita prasideda rezervuotu žodžiu importas ir tęsiamas identifikatoriumi, po kurio pasirinktinai seka taškų atskirtų identifikatorių seka. Tipo pavadinimas arba žvaigždutė (*) ir kabliataškis nutraukia šį teiginį.

Sintaksė atskleidžia dvi importo ataskaitos formas. Pirmiausia galite importuoti vieno tipo pavadinimą, kuris identifikuojamas per typeName. Antra, galite importuoti visus tipus, kurie identifikuojami per žvaigždutę.

* simbolis yra pakaitos simbolis, žymintis visus nekvalifikuotus tipų pavadinimus. Kompiliatorius liepia ieškoti tokių pavadinimų dešiniajame pakete importo sakinio paketų sekos, nebent tipo pavadinimas randamas anksčiau ieškotame pakete. Atkreipkite dėmesį, kad naudojant pakaitos simbolį nėra baudos už veikimą ar dėl to, kad kodas išsipučia. Tačiau tai gali sukelti vardų konfliktus, kuriuos pamatysite.

Pavyzdžiui, importuoti ca.javajeff.graphics.Triangle; kompiliatoriui pasako, kad nekvalifikuotas Trikampis klasė egzistuoja ca.javajeff.grafika pakuotė. Panašiai kažkas panašaus

 importuoti ca.javajeff.grafiką. *; 

liepia kompiliatoriui pažvelgti į šį paketą, kai jis susiduria su Trikampis vardas, a Apskritimas vardas, ar net Sąskaita vardas (jei Sąskaita dar nebuvo rasta).

Venkite * daugelio kūrėjų projektuose

Dirbdami su kelių kūrėjų projektu, venkite naudoti * pakaitos simbolis, kad kiti kūrėjai galėtų lengvai pamatyti, kurie tipai naudojami jūsų šaltinio kode.