Introduzione ai Package in Java

Concetti Chiave
  • I package in Java sono contenitori per classi che aiutano a gestire lo spazio dei nomi e la visibilità delle classi.
  • Un package può essere definito con l'istruzione package all'inizio di un file sorgente Java.
  • I package sono organizzati in una gerarchia e devono essere riflessi nel sistema di file.
  • Il sistema di esecuzione Java cerca i package nella directory corrente, nei percorsi specificati dalla variabile d'ambiente CLASSPATH, o tramite l'opzione -classpath.

Package

In Java, I package sono contenitori per classi. Sono utilizzati per mantenere lo spazio dei nomi delle classi compartimentalizzato.

Ad esempio, un package consente di creare una classe chiamata Lista, che può essere memorizzata nel proprio package senza preoccuparsi che entri in conflitto con un'altra classe chiamata Lista archiviata altrove. I package sono memorizzati in maniera gerarchica e vengono importati esplicitamente nelle nuove definizioni di classe.

Nelle lezioni precedenti, il nome di ciascuna classe di esempio è stato preso dallo stesso spazio dei nomi. Questo significa che è stato necessario usare un nome univoco per ogni classe per evitare collisioni di nomi.

Dopo un po', senza un modo per gestire lo spazio dei nomi, si potrebbe esaurire l'uso di nomi comodi e descrittivi per le singole classi. Serve anche un modo per assicurarsi che il nome scelto per una classe sia ragionevolmente univoco e non collida con nomi di classi scelti da altri programmatori.

Fortunatamente, Java fornisce un meccanismo per suddividere lo spazio dei nomi delle classi in blocchi più gestibili. Questo meccanismo è il package. Il package è sia un meccanismo di denominazione sia un meccanismo di controllo della visibilità. È possibile definire classi all'interno di un package che non sono accessibili dal codice esterno a quel package. Si possono anche definire membri di classe che sono visibili solo ad altri membri dello stesso package. Ciò consente di avere un maggiore controllo sull'ambito e la visibilità delle classi.

Definire un Package

Creare un package è piuttosto semplice: basta includere un comando package come prima istruzione in un file sorgente Java.

Tutte le classi dichiarate all'interno di quel file apparterranno al package specificato. L'istruzione package definisce uno spazio dei nomi in cui sono archiviate le classi. Se si omette l'istruzione package, i nomi delle classi sono inseriti nel package predefinito, che non ha nome. (Ecco perché finora non è stato necessario preoccuparsi dei package.) Sebbene il package predefinito sia adatto per programmi di esempio brevi, è inadeguato per applicazioni reali. La maggior parte delle volte, sarà necessario definire un package per il codice.

Questa è la forma generale dell'istruzione package:

package nome_package;

Qui, nome_package è il nome del package. Ad esempio, la seguente istruzione crea un package chiamato miopackage:

package miopackage;

Tipicamente, Java utilizza directory del file system per memorizzare i package.

Ad esempio, i file .class per le classi dichiarate come parte di miopackage devono essere memorizzati in una directory chiamata miopackage. Si ricordi che in questo caso le lettere maiuscole e minuscole sono significative e il nome della directory deve corrispondere esattamente al nome del package.

Più di un file può includere la stessa istruzione package. L'istruzione package specifica semplicemente a quale package appartengono le classi definite in un file. Non esclude altre classi in altri file dall'essere parte dello stesso package. La maggior parte dei package del mondo reale sono distribuiti su molti file.

È possibile creare una gerarchia di package. Per farlo, basta separare ciascun nome di package da quello sopra di esso usando un punto. La forma generale di un'istruzione package multilivello è mostrata qui:

package nome1_package[.nome2_package[.nome3_package]];

Una gerarchia di package deve essere riflessa nel sistema di file dell'ambiente di sviluppo Java. Ad esempio, un package dichiarato come:

package a.b.c;

deve essere memorizzato in una struttura di directory a\b\c in un ambiente Windows. Oppure, in un ambiente Unix, deve essere memorizzato in una struttura di directory a/b/c. In altre parole, il nome del package deve corrispondere al percorso della directory in cui sono archiviate le classi.

Assicurarsi di scegliere nomi di package accurati. Non è possibile rinominare un package senza rinominare la directory in cui sono archiviate le classi.

Posizione dei Package e CLASSPATH

Come appena spiegato, i package sono tipicamente rispecchiati da directory.

Questo solleva una domanda importante: come fa il sistema di esecuzione Java a sapere dove cercare i package che vengono creati? Per quanto riguarda gli esempi di questa guida, la risposta ha tre parti.

Primo, per impostazione predefinita, il sistema di esecuzione Java utilizza la directory di lavoro corrente come punto di partenza. Pertanto, se un package si trova in una sottodirectory della directory corrente, sarà trovato.

Ad esempio, se si trova nella directory corrente una sottodirectory chiamata miopack, e questa contiene un file .class per una classe chiamata Esempio, allora il programma può essere eseguito con il comando:

java miopack.Esempio

Secondo, è possibile specificare uno o più percorsi di directory impostando la variabile d'ambiente CLASSPATH.

Terzo, è possibile utilizzare l'opzione -classpath con java e javac per specificare il percorso delle classi. È utile sottolineare che, a partire da JDK 9, un package può essere parte di un modulo, e dunque risiedere nel percorso dei moduli. Tuttavia, la trattazione dei moduli e dei percorsi dei moduli è rimandata alle prossime lezioni. Per ora, useremo solo percorsi di classi.

Ad esempio, considerare la seguente dichiarazione di package:

package miopack;

Affinché un programma possa trovare miopack, il programma può essere eseguito da una directory immediatamente sopra miopack, oppure la variabile d'ambiente CLASSPATH deve essere impostata per includere il percorso a miopack, oppure l'opzione -classpath deve specificare il percorso a miopack quando il programma viene eseguito tramite java.

Quando si usano le ultime due opzioni, il percorso delle classi non deve includere miopack stesso. Deve semplicemente specificare il percorso verso miopack. Ad esempio, in un ambiente Windows, se il percorso a miopack è:

C:\MieiProgrammi\Java\miopack

allora il classpath per miopack è:

C:\MieiProgrammi\Java

Quindi, se si usa l'opzione -classpath, il comando per eseguire il programma sarà:

java -classpath C:\MieiProgrammi\Java miopack.Esempio

Analogamente, se si usa la variabile d'ambiente CLASSPATH, prima si imposta CLASSPATH su C:\MieiProgrammi\Java:

set CLASSPATH=C:\MieiProgrammi\Java

Quindi, il comando per eseguire il programma sarà:

java miopack.Esempio

Il modo più semplice per provare gli esempi mostrati in questa guida è semplicemente creare le directory dei package sotto la directory corrente di sviluppo, inserire i file .class nelle directory appropriate e poi eseguire i programmi dalla directory di sviluppo. Questo è l'approccio utilizzato nell'esempio seguente.

Un breve esempio di Package

Tenendo presente la discussione precedente, è possibile provare questo semplice package:

// Un semplice package
package miopack;

class Saldo {
    String nome;
    double saldo;

    Saldo(String n, double b) {
        nome = n;
        saldo = b;
    }

    void mostra() {
        if(saldo<0)
            System.out.print("--> ");
        System.out.println(nome + ": $" + saldo);
    }
}

class ContoSaldo {
    public static void main(String[] args) {
        Saldo[] corrente = new Saldo[3];

        corrente[0] = new Saldo("K. J. Fielding", 123.23);
        corrente[1] = new Saldo("Will Tell", 157.02);
        corrente[2] = new Saldo("Tom Jackson", -12.33);

        for(int i=0; i<3; i++) corrente[i].mostra();
    }
}

Salvare questo file come ContoSaldo.java e inserirlo in una directory chiamata miopack.

Poi, compilare il file. Assicurarsi che il file risultante .class si trovi anch'esso nella directory miopack. Quindi, provare a eseguire la classe ContoSaldo usando la seguente riga di comando:

java miopack.ContoSaldo

Si ricordi che è necessario trovarsi nella directory sopra miopack quando si esegue questo comando. (In alternativa, è possibile usare una delle altre due opzioni descritte nella sezione precedente per specificare il path a miopack.)

Come spiegato, ContoSaldo è ora parte del package miopack. Questo significa che non può essere eseguito da solo. Vale a dire, non è possibile usare questa riga di comando:

java ContoSaldo

ContoSaldo deve essere qualificato con il nome del suo package.