Helsingin yliopisto / Tietojenkäsittelytieteen laitos / 581258-1 Johdatus ohjelmointiin
Copyright © 1997 Arto Wikla. Tämän oppimateriaalin käyttö on sallittu vain yksityishenkilöille opiskelutarkoituksissa. Materiaalin käyttö muihin tarkoituksiin, kuten kaupallisilla tai muilla kursseilla, on kielletty.

4.6 Pakkaus

(Edellinen muutos 25.11.1997)
(Muutettu viimeksi 4.12.2001: CLASSPATH-muuttujan asetus)

Ohjelmiston tuotannossa yksi keskeinen ongelma on ohjelman osien, erilaisten ohjelmatiedostojen hallinta: missä mikin osa sijaitsee, miten osat löydetään.

Javassa ohjelmatiedostot eli class-tiedostot kerätään ns. pakkauksiin (package). Itse pakkaukset voidaan järjestää puumaiseen tiedostorakenteeseen. Pakkaus ei sinänsä liity olio-ohjelmointiin. Se on käytännön ohjelmistotuotannon väline!

Yhteen pakkaukseen on tapana kerätä luokkia (ja rajapintaluokkia), jotka tavalla tai toisella liittyvät toisiinsa. Jos luokkia on paljon, pakkaukset voidaan jäsennellä alipakkauksiksi, jne.

Myös Java-kielen valmiit välineet on toteutettu pakkauksina: Esimerkiksi pakkaus java muodostuu alipakkauksista java.lang, java.util, java.io, ...

Pakkaus muodostaa "nimiavaruuden", jonka nimien näkyvyys pakkauksen ulkopuolelle voidaan sallia tai kieltää. (Myös pakkauksen sisällä nimien näkyvyys luokkien välillä on säädeltävissä, kts. 4.6)

Käännösyksikkö

Käännösyksikkö (compilation unit) on tiedosto, joka voi sisältää (tässä järjestyksessä!):

Jos tiedoston alussa ei ole package-määrettä, class-tiedostot asetetaan ns. nimettömään pakkaukseen. Se on Java-toteutuksissa yleensä "nykyhakemisto", so. hakemisto, jossa class-tiedosto sijaitsee.

Huom: Käännösyksikössä voi olla vain yksi luokka, jolle on määritelty näkyvyydeksi public!

Jokaisesta käännösyksikön sisältämästä Java-kielisestä class-määrittelystä tehdään erillinen Bytecode-kielinen class-tiedosto. Pakkauksiin kerätään nimenomaan näitä class-tiedostoja.

Package-määrittely

Käännösyksikön alussa oleva määrittely
  package paketti;
ilmaisee, että käännösyksikön sisältämät luokat on käännettyinä määrä sijoittaa pakkaukseen paketti. Useissa käännösyksiköissä voi olla sama pakkauksen nimi.

Huom: package-ilmaus ei automaattisesti vie syntyviä class-tiedostoja pakkausta vastaavaan hakemistoon!

Käännösyksikön kuuluminen alipakkaukseen ilmaistaan:

   package paketti.alipaketti;

Pakkauksen kaikki luokat saavat "etunimekseen" pakkauksen nimen! Esimerkiksi käännösyksiköiden
  package pak;
  public class Aapeli {
    ...
  }
ja
  package pak; 
  public class Beepeli {
    ...
  }
luokkien koko nimet ovat pak.Aapeli ja pak.Beepeli.

Import-määrittely ja pakkauksen käyttö

Pakkauksen julkisiin luokkiin (public) voi pakkauksen ulkopuolelta viitata luokan täydellisellä nimellä, esimerkiksi:
  class sovellutututus {
    ...
    pak.Aapeli x = new pak.Aapeli();
    ...
  }
Näin voi menetellä, jos pakkauksen välineitä ei käytetä paljon, ja jos ohjelmaa ei ole tarkoitus ylläpitää!

Käytännössä on järkevää käyttää aina import-ilmauksia. Ne kirjoitetaan käännösyksikön alkuun mahdollisen package-ilmauksen jälkeen. Näin heti käännösyksikön alusta näkee, mitä pakkauksia luokissa käytetään.

Esimerkki: Käännösyksikkö olkoon seuraavanlainen:

  package omapaketti;

  import pak1.Luo1;
  import pak2.*;
  import pak3.pak4.*;

  class Oma1 { ... }
  class Oma2 { 
    ... 
    pak5.Kissa a = new pak5.Kissa();
    ...
  }
Tässä Huomautuksia:

Pakkausten nimet

Pakkauksiin on syytä koota keskenään yhteenliittyviä luokkia. Jos luokkia on paljon, ne voidaan jakaa edelleen alipakkauksiin. Jos tämä jäsentely tehdään hyvin, pakkausten nimien keksimisen ei pitäisi olla suuri ongelma.

Tulevaisuuden visioissa Java-pakkaukset on haluttu nähdä koko Internetin nimiavaruudessa. Tähän tarkoitukseen on suositeltu ns. domain-nimestä johdettujen nimien käyttöä pakkauksen nimen alkuosana.

Esimerkiksi sitten, kun Lue-luokka otetaan maailmanlaajuiseen käyttöön :-), siihen voi viitata vaikkapa nimellä:

  FI.helsinki.cs.util.io.Lue


Pakkaukset, hakemistot ja tiedostot

Pakkausten säilyttämisen tapa on Java-kielen ulkopuolinen asia. Esimerkikiksi Unixissa/Linuxissa ja Windows 95 -järjestelmässä luonteva vastine pakkausten puumaiselle rakenteelle on puumainen hakemistorakenne.

Pakkaukset voitaisiin sijoittaa myös tietokantaan tai vaikkapa ripotella "ympäri internettiä" kunhan vain käytettävä Java-toteutus tietää, mistä etsiä!

Pakkaukset Unixissa/Linuxissa (bash-shell)

Unix- ja Linux-järjestelmissä Java-toteutus etsii pakkauksia hakemistoista, jotka on ilmoitettu erään ns. ympäristömuuttujan arvona. Ympäristömuuttuja CLASSPATH tuntee oletusarvoisesti Java-kieleen valmiiksi määriteltyjen pakkausten sijainnin. Kun omien pakkausten sijainti hakemistorakenteessa lisätään muuttujan arvoon, Java-toteutus löytää myös omat pakkaukset.

Jos pakkaukset on tarkoitettu pysyvään käyttöön, CLASSPATH-muuttujaa voi täydentää pysyvästi.

Esimerkki:


Takaisin luvun 4 sisällysluetteloon.