Helsingin yliopisto / Tietojenkäsittelytieteen laitos
Copyright © 2005 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

(Muutettu viimeksi 13.6.2005)

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!

Kääntäjä tuottaa jokaisesta käännösyksikön sisältämästä Java-kielisestä luokkamäärittelystä erillisen Bytecode-kielisen class-tiedoston. Ja pakkauksiin siis 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 kun jokin itse tehty luokka - vaikkapa MinunIkiomaLuokkani - annettaisiin maailmanlaajuiseen käyttöön, siihen voitaisiin viitata vaikkapa nimellä:

  fi.helsinki.cs.wikla.MinunIkiomaLuokkani
Huom. Näin asiat eivät siis vielä ole! Mahtanevatko koskaan ollakaan?

Pakkaukset, hakemistot ja tiedostot

Pakkausten säilyttämisen tapa on Java-kielen ulkopuolinen asia. Esimerkikiksi Unixissa/Linuxissa ja Windows-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.