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ö (compilation unit) on tiedosto, joka voi sisältää (tässä järjestyksessä!):
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 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.
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ä
import java.lang.*;
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 voitaisiin sijoittaa myös tietokantaan tai vaikkapa ripotella "ympäri internettiä" kunhan vain käytettävä Java-toteutus tietää, mistä etsiä!
Jos pakkaukset on tarkoitettu pysyvään käyttöön, CLASSPATH-muuttujaa voi täydentää pysyvästi.
Esimerkki:
export CLASSPATH="$CLASSPATH:$HOME/classes"Huom: Laitoksen ylläpidon Jani Jaakkolan mukaan tämä komento toimii laitoksen kaikissa Linuxeissa ja Unixeissa. (4.12.2001)
[Se vanha komento oli:
setenv CLASSPATH $CLASSPATH:$HOME/classes
Joissakin virityksissä tuota voi ehkä joutua käyttämään... :-]
Nyt Java-toteutus osaa etsiä pakkauksia myös kotihakemiston alihakemistosta classes.
package kalut;
public class Koe {
public int x, y;
}
Käännetään luokka ja sijoitetaan käänöksen tulos
Koe.class hakemistoon classes/kalut.
import kalut.*;
class Sov {
public static void main(String[] args) {
Koe a = new Koe();
a.x = 5; a.y = 6;
System.out.println(a.x+" "+a.y);
}
}
Tässä annetaan lupa hakea mikä tahansa julkinen luokka pakkauksesta
kalut. (Myös pelkkä import kalut.Koe; riittäisi
tässä tapauksessa.)
Takaisin luvun 4 sisällysluetteloon.