Packages e import
I package
Un package è un insieme di entità di Java (classi, interface, enum, exceptions e errors) che si pensa siano correlate. I package sono usati per:
Risolvere problemi di conflitti di classi mettendo il nome del package come prefisso al nome della classe. Per esempio
com.zzz.Circle
ecom.yyy.Circle
sono due classi distinte. Sebbene condividano lo stesso nome di classeCircle
ma appartengono a due packega differenti:com.zzz
ecom.yyy
. Queste due classi possono essere usate nello stesso programma e distinte utilizzando il nome completo (fully-qualified class name), il nome del pacchetto più il nome della classe.Controllo visibilità: oltre a public e private per i modificatori di accesso Java ha protected e default che sono collegati alla funzionalità di package. Una entity protected (attributo e metodo di un oggetto) di una classe è accedibile da classi nello stesso package e da sottoclassi della medesima classe. Una entità senza nessun specificatore d'accesso (default) è accedibile da solo le classi nello stesso package.
Per distribuire una collezione di classi riutilizzabili in un formato conosciuto come Java Archive (JAR).
Package name & struttura delle directory
Il nome del package rispecchia la struttura delle directory utilizzate per salvare la classe. Per esempio il codice sorgente della classe Circle
del package com.zzz
è salvato in "$BASE_DIR/com/zzz/Circle.java
", dove $BASE_DIR
denota la directory base del pacchetto. Chiaramente, al "punto" nel nome del package corrisponde una sub directory nel file system.
La directory base ($BASE_DIR
) può essere stabilita ovunque nel vostro file system. Il compilatore Java e il runtime deve essere informato della posizione della $BASE_DIR
così che può trovare le classi. Questo avviene tramite la variabile d'ambiente chiamata CLASSPATH
. (CLASSPATH
è simile ad un altra variabile d'ambiente PATH
, che è usata dalla shell dei comandi per cercare gli eseguibili).
Creazione dei package
Per far si che una classe appartenga a un package, bisogna mettere lo statement del package come prima riga del codice sorgente. Esempio della classe com.zzz.Circle
:
Notate lo statement package
all'inizio del codice sorgente della classe.
Come già detto un' altra classe Circle
potrebbe essere definita ma dovrebbe stare in un altro package, ad esempio, com.yyy
:
Come si può notare, la classe è stata definita in un altro package.
Se volessimo utilizzare una delle due classi all'interno di un altra classe, ad esempio di nome TestCircle
, dobbiamo:
Se la classe è nello stesso package di una delle due
Circle
, se non specificato diversamente (tramite istruzione import), utilizza la classe del suo stesso package - perché di default gli è visibile; per utilizzare la classe nell'altro package devo fare l'import della classe nell'altro package in modo da specificare il nome completo e renderla visibile (in questo modo non c'è ambiguità);Se la classe
TestCircle
è in altro package rispetto alla classeCircle
che si vuole utilizzare, è obbligatorio eseguire l'import per renderla visibile;Se la classe
TestCircle
vuole utilizzare contemporaneamente le due versioni diCircle
, quella in packagecom.zzz
ecom.yyy
, deve specificare ogni volta il nome completo, per togliere l'ambiguità su quella a cui ci si riferisce.
Alcuni casi, esemplificativi, qui sotto, con due classi Circle
in due package diversi:
Eseguendo il programma com.yyy.TestCircle
, utilizzo le due versioni di Circle
:
ottengo come output:
Eseguendo il programma com.zzz.TestCircle
, per utilizzare la versione di Circle
di un altro package, devo importarla esplicitamente::
ottengo a console;
Mentre, eseguendo il programma com.ppp.TestCircle
:
ottengo l'output:
Mentre non si sarebbe potuto eseguire due import perché avrebbe generato ambiguità:
Esercizi sui package
http://www3.ntu.edu.sg/home/ehchua/programming/java/J9c_PackageClasspath.html
I package della Standard library
I package principali del JDK (detta anche la standard library, libreria standard che si ha a disposizione installato il Java Development Kit ) sono:
Per utilizzare queste classi è necessario fare l'import dando tutto il nome compreso il package.
Come per qualsiasi altra classe di cui avessi bisogno e non è nello stesso package della classe utilizzatrice, ho bisogno di scrivere nel codice import <Class-name> dove classe name comprende il package ad esempio, import java.io.FileInputStream
, qualora ti servisse la classe FileInputStream per leggere il contenuto dei file.
Esempio programma, che legge il contenuto di un file di testo e lo stampa a video:
In questo caso ho importato le classi java.io.BufferedReader
, java.io.FileReader
e java.io.IOException
, per le operazioni di input. Le classi String
e System
non è necessario importarle in quanto sono del package java.lang
e sono sempre importate.
Se volessi importare tutte la classi del package java.io
potrei anche scrivere java.io.*
. Quindi il programma precedente può anche essere scritto nel seguente modo:
Nota bene:
non c'è distinzione tra classi standard (della standard library) e classi scritte da noi o prese utilizzando librerie di terze parti: se ho bisogno di una classe che sia richiamata dalle mia classe e la classe di cui ho bisogno si trova in un altro package, allora per accedere alla classe devo importarla (import <Class-name>), comprensiva del nome del package;
per le classi sotto java.lang.* non è necessario eseguire l'import in quanto sono sempre importate;
Vedete ad esempio le classi della libreria standard https://docs.oracle.com/javase/7/docs/api/ come sono organizzate in package. Selezionando il package nella documentazione accederete alle diverse classi del package. Vedete anche che spiega come è organizzata la documentazione della libraria standard Documentation & JavaDoc.
Classi di terze parti
Finora abbiamo parlato di utilizzo di classi scritte da noi e l'utilizzo di classi della standard library, ad esempio, java.util.Vector, cosa dobbiamo fare per utilizzare una libraria scritta da altri, ad esempio, che è possibile scaricare da internet e ci fornisce una funzionalità di cui abbiamo bisogno ( e non abbiamo il tempo o la voglia o richiede competenze così specifiche che non abbiamo)?
Concetto di CLASSPATH
Import e Static import
Vediamo ora un'estensione della direttiva static che può essere comoda. Abbiamo visto che import rende possibile riferire una classe come java.util.Scanner
utilizzando il nome semplice Scanner
. Ma dobbiamo ancora utilizzare i nomi composti alle variabili statiche come System.out
o ai metodi statici come Math.sqrt
.
C'è un'altra forma di import che può essere utilizzata per importare membri statici di una classe nello stesso modo di come che la direttiva import è utilizzata per importare classi di un package. La direttiva è chiamata static import e ha la sintassi:
per importare un membro statico da una classe, o
per importare tutti i membri statici di una classe. Per esempio, se mettiamo
allora possiamo usare nel codice, il semplice nome out
, invece del nome composito, System.out
. Vuol dire che possiamo scrivere out.println
invece di System.out.println
. Se nel codice dobbiamo utilizzare molti metodi della classe Math, si può usare la sintassi:
Questo permette di utilizzare direttamente sqrt
invece di Math.sqrt
, log
invece di Math.log
e PI
invece di Math.PI
.
Last updated