Iniziamo con questo articolo la nostra panoramica su uno dei linguaggi di programmazione più famosi del mondo, Java. In questa prima puntata ci proponiamo di chiarire alcuni concetti di base, necessari per avere una discreta comprensione non solo del linguaggio in senso stretto, ma anche delle sue peculiarità rispetto ad altri linguaggi e delle potenzialità che Java offre.
Prima di cominciare, potete trovare qui informazioni circa le risorse che impiegheremo durante questi articoli, gli scopi e una breve storia del linguaggio.
Che cos’è Java? Java è un linguaggio di programmazione orientato agli oggetti con una struttura ibrida di compilazione e interpretazione. Cercheremo adesso di fare chiarezza su questi due punti fondamentali.
Java è un linguaggio di programmazione orientato agli oggetti.
Java fa parte di quella generazione di linguaggi di programmazione che fanno riferimento al cosiddetto “paradigma della programmazione ad oggetti“. Di questa famiglia fanno parte la stragrande maggioranza dei linguaggi attualmente più utilizzati (da C++ a VB), delineando un netto distacco rispetto alla programmazione imperativa, particolarmente diffusa fino a qualche anno fa (che aveva nel linguaggio C l’esponente forse più celebre, se non altro per l’associazione immediata col kernel di Unix).
Fondamentalmente il paradigma della programmazione ad oggetti si fonda sui seguenti cardini:
1. Il metodo ed il linguaggio devono avere la nozione di classe come loro concetto principale
2. Ogni cosa è un oggetto, e gli oggetti sono definiti dalle classi
3. Gli oggetti interagiscono tra loro esclusivamente tramite i metodi
4. Le classi dovrebbero essere i soli moduli (vedremmo che questo in Java non è vero)
5. Il linguaggio deve permettere il meccanismo dell’ereditarietà, eventualmente controllandolo
Per i nostri scopi è necessario capire subito il significato dei primi tre punti che potrebbero risultare oscuri a chi non ha esperienza di programmazione.
In un linguaggio di programmazione ad oggetti il programma vero e proprio è dato da una collezione di oggetti che interagiscono tra di loro tramite i cosiddetti messaggi, ovvero l’esecuzione di una determinata azione è richiesta sempre da un determinato oggetto (in realtà in Java esiste un’altra via che vedremmo più avanti).
Pensate ad un televisore: si tratta di uno strumento che, per esempio, sa accendersi, sa sintonizzarsi su canali specifici, sa spegnersi. Ogni azione è però richiesta esplicitamente da parte dell’utente, servendosi di un altro oggetto (il telecomando).
In pratica, è il telecomando che invia al televisore un messaggio comunicandogli quale azione deve essere intrapresa. Il televisore poi è in grado di conoscere il suo stato attuale ossia le proprie proprietà (il televisore è acceso o spento? Su quale canale è sintonizzato?). Analogamente, anche gli oggetti software dialogano tra loro per mezzo di messaggi ed ogni oggetto è caratterizzato da un insieme di proprietà che ne descrivono lo stato.
I linguaggi di programmazione più moderni fanno uso degli oggetti software per rendere la scrittura dei programmi più semplice e più intuitiva. Non è richiesta, infatti, al programmatore la conoscenza sul funzionamento “interno” dell’oggetto software (chi utilizza il televisore non deve sapere come sono strutturati i circuiti elettronici che gli permettono di funzionare…): gli è sufficiente apprendere le modalità per colloquiare con lui, ossia i messaggi che possono essere inviati e l’effetto di ogni singolo messaggio (semantica). Questa importante caratteristica prende il nome di incapsulamento.
In pratica se vogliamo scrivere un programma che cosa dobbiamo fare? Dobbiamo scrivere una classe per ogni tipo di oggetti (nel nostro caso una classe “televisore” ed una classe “telecomando”): le classi sono infatti il modello degli oggetti che intendiamo usare.
Facendo un altro esempio, il progetto di un’abitazione rappresenta la classe ma in se stesso non è veramente una casa. Solo una volta che la casa sarà stata costruita avremo un oggetto di tipo “casa” così come l’avevamo progettato; è solo a questo punto che l’oggetto esiste e – dal nostro punto di vista – occupa memoria del calcolatore ed è accessibile tramite un identificatore.
Notate che tuttavia esiste una certa relazione stretta tra la casa e il suo progetto, poiché per costruirne un’altra completamente diversa abbiamo bisogno di un altro progetto. In generale, quindi, nella classe non è riservata memoria per i dati, cosa che invece viene fatta quando si istanziano uno o più oggetti.
Tornando al nostro esempio del televisore dopo aver definito le classi che ci interessano dovrebbe essere a questo punto chiaro che abbiamo bisogno di istanziare (“costruire”) un televisore ed un telecomando (impareremo presto come si fa in Java…) e usare l’oggetto telecomando per dare “ordini” al televisore. Questi ordini vengono impartiti tramite l’invocazione dei metodi sui due oggetti, ed è infatti solo all’interno dei metodi che è permesso l’uso di istruzioni vere e proprie (è solo all’interno dei metodi che avviene la computazione).
Rimane ancora da capire come deve essere costruita logicamente la classe dal punto di vista dei dati da memorizzare. Pensate al progetto della casa: esso deve contenere il numero e la disposizione di porte, finestre, muri, le loro caratteristiche (spessore, materiale, ecc…) e tutta una serie di altri dettagli. Allo stesso modo ci dovremmo comportare col televisore e il telecomando. Come già detto in precedenza, il televisore deve avere memorizzato da qualche parte il suo stato attuale (on/off), il suo canale corrente e quanti più dettagli volete, così come il telecomando deve avere il numero e la disposizione dei tasti, per esempio.
Com’è facile comprendere dagli esempi illstrati sinora, la programmazione ad oggetti ha un alto livello di astrazione rispetto alla macchina e può risultare più ostica almeno all’inizio. L’evidente vantaggio è che una volta compreso il meccanismo potete pensare al problema da risolvere nei termini del problema stesso (visto che nel mondo reale esistono gli oggetti) e non nei termini della macchina su cui lo dovrete eseguire.
I punti 4) e 5) saranno più chiari man mano che andremo avanti, così come il meccanismo della definizione delle classi e quindi degli oggetti sarà più chiaro molto presto, non appena cominceremo a scrivere il nostro primo codice Java.
Java come linguaggio multi-piattaforma: il bytecode
Java ha una implementazione ibrida di compilazione ed interpretazione.
E’ certamente chiaro a tutti che quando si programma si scrive codice in un linguaggio accessibile all’uomo e non alla macchina, giacché i calcolatori come li conosciamo noi sono in grado di comprendere esclusivamente un “linguaggio fatto di 0 e 1”. Rimane quindi da capire in quale modo il linguaggio comprensibile all’uomo col quale programmiamo diventi operativo sulla macchina. Esistono due vie per far questo:
1. tradurre interamente il nostro sorgente in codice macchina (compilazione)
2. eseguire un programma in grado di fare da ponte tra i due i codici a run-time (interpretazione)
Per seguire la seconda via si fa uso di quello che si chiama interprete dei comandi, che altro non è che un software che fa sembrare all’utente (il programmatore e il suo sorgente, a seconda dei punti di vista) di utilizzare un processore dedicato in grado di comprendere autonomamente le istruzioni del linguaggio in questione. In Java questo compito è assolto dalla JVM (Java Virtual Machine).
Java però, come abbiamo detto, ha un’implementazione ibrida: questo significa che non sono direttamente i sorgenti scritti dal programmatore a essere interpretati, ma dei codici intermedi chiamati bytecode. Per chiarirci subito dal punto di vista pratico i sorgenti sono immagazzinati nel file system con estensione .java, i bytecode con estensione .class e questi ultimi costituiscono il vero e proprio programma Java pronto per l’uso.
Questa particolare “conformazione” del linguaggio, a prima vista inutile, conferisce allo stesso una caratteristica unica nel panorama dei linguaggi di programmazione: Java è un linguaggio multi-piattaforma. Questo significa che lo stesso bytecode è eseguibile su tutti le maggiori piattaforme del mondo (ovvero su tutte quello per cui esista l’interprete opportuno) a patto di aver installato l’opportuna JVM.
E’ per questo motivo che Java è particolarmente impiegato per la creazione di applet nei siti web, garantendo alle stesse di essere visibili alla stragrande maggioranza di utenti del mondo.
Generalmente i linguaggi interpretati sono alcune volte più lenti dei linguaggi compilati, nel senso che un determinato programma C++ sarà alcune volte più veloce dell’omologo Java, questo è in effetti il prezzo da pagare. A titolo conoscitivo, segnaliamo che esiste una procedura non troppo semplice di compilazione integrale di codice Java tramite il cosiddetto JIT (Just In Time) che però fa perdere la portabilità del codice e non raggiunge appieno i valori di velocità, ad esempio, propri del C++.
Fatte queste dovute precisazioni cominciamo ad occuparci del linguaggio vero e proprio. Decidiamo di partire immediatamente con un esempio classico, il cui contenuto ci permetterà di spiegare un buon numero di concetti indispensabili per programmare Java:
public class HelloWorld
{
public static void main(String[] args)
{
System.out.println("HelloWorld by ilsoftware.it");
}
}
che deve essere salvata in un file dal nome HelloWorld.java
esattamente così come è scritto: prestate attenzione quando effettuate queste operazioni perché Java è case-sensitive ovvero distingue le minuscole dalle minuscole.
Tutte le classi dichiarate public devono essere salvate in un file che abbia esattamente lo stesso nome.
Il listato si apre con la dichiarazione della classe mediante le parole riservate del linguaggio class e public. Quest’ultima consente di specificare che la classe può essere utilizzabile da qualunque altro programma lo desideri : dovete considerare che in ogni progetto deve esistere almeno una classe public che possa essere utilizzata dall’ambiente a run-time.
Con questa precisazione chiudiamo l’introduzione relativa ai concetti base da tenere a mente. Siamo ora pronti ad affrontare la parte relativa al linguaggio di programmazione vero e proprio.
Nel prossimo articolo spiegheremo passo passo il codice del nostro primo esempio e cercheremo di capire la struttura generale di un programma Java.
Storia, materiale e segnalazioni
Quando ho deciso di scrivere questo documento l’ho fatto perché so che genericamente nel momento in cui ci si avvicina al mondo della programmazione è molto utile avere una guida teorica valida, ma è altrettanto utile un supporto per la risoluzione immediata dei primi problemi pratici e per fugare alcuni dubbi che inevitabilmente sorgono.
Cominciamo chiarendo che Java è un linguaggio di programmazione sviluppato interamente da una società, Sun Microsystem, con degli obbiettivi precisi: creare un linguaggio usufruibile dal maggior numero possibile di programmatori (professionisti e non) fortemente orientato alla programmazione in rete e che fosse, per questo, interpiattaforma. Java è e rimane un linguaggio di programmazione general-purpose; benché particolarmente adatto alla programmazione in rete, non ha alcuna parentela diretta o indiretta con JavaScript e JScript. Questi ultimi due sono linguaggi di scripting (solo ed esclusivamente di scripting) nati dai colossi del web browsing Miscrosoft e Netscape per i rispettivi browser, con Microsoft che arrivò in seconda battuta. I tre linguaggi in questione non hanno niente in comune, se non per certi versi una sintassi simile che però non deve ingannare: è simile anche ad altri linguaggi di programmazione orientati agli oggetti (in effetti la sintassi di Java è molto simile a quella del C/C++ poiché il primo intento di Sun fu quello di rendere il nuovo linguaggio fruibile in tempi brevi al gran numero di programmatori C e C++).
L’essenziale: Java Development Kit. Editor free e a pagamento.
Per programmare in Java è indispensabile avere installato il cosiddetto JDK (Java Development Kit) scaricabile gratuitamente da qui (30MB circa; scegliete la piattaforma che vi interessa) che fornisce le classi standard del linguaggio, l’interprete, il compilatore ed alcune altre utilities (tra cui Javadoc, Javaw).
Questo è sufficiente per programmare Java, sebbene sia necessario operare da riga di comando. Tuttavia, vista la presenza di ambienti semplici anche con licenza freeware, questa pratica è poco diffusa. Segnalo, a titolo d’esempio, JCreator tra gli ambienti freeware (con il quale vengono testati tutti gli esempi posti in queste pagine) e l’ottimo JBuilder tra gli ambienti a pagamento, dotato di funzionalità tali da rendere la creazione di una interfaccia gradevole un’operazione molto semplice.
Potete scaricare Jcreator all’indirizzo www.jcreator.com (scegliete la sezione Download; in calce alla pagina trovate la versione free).
A pagina seguente trovate alcuni semplici informazioni su come usare l’ambiente.
Per quanto riguarda il prodotto Borland lo potete trovare in versione dimostrativa da 30 giorni allegato a molte riviste, versione integrale da attivare on-line.
Documentazione Java
Rimane ora solamente da chiarire quali siano i migliori supporti che si dovrebbero avere a portata di mano durante la programmazione in Java: personalmente ritengo che l’unica cosa veramente fondamentale sia la documentazione ufficiale della JDK anche questa gratuitamente scaricabile da questa pagina (30MB circa; cercate in fondo alla pagina).
In aggiunta, per chi fosse interessato ad un manuale di più ampio respiro del linguaggio è ormai diventato una pietra miliare Thinking in Java di Bruce Eckel, scaricabile da qui (nel momento in cui scrivo la terza edizione non è ancora disponibile in versione completa, lingua inglese) oppure reperibile in libreria edito in italiano da Apogeo Editore.
Come eseguire i programmi Java in ambiente Windows
Per concludere, affrontiamo il problema dell’esecuzione dei programmi creati in Java in ambiente Microsoft Windows: si tratta infatti di un aspetto spesso problematico per chi si avvicina al linguaggio.
La versione compilata del vostro progetto sarà costituita da uno o più file con estensione .class. Se proverete a cliccare due volte su qualsiasi file .class, Windows non troverà alcun programma standard per eseguirlo e ve lo segnalerà. Il modo standard per eseguire i programmi Java è quindi quello di creare dei file batch che contengano semplicemente una riga come la seguente:
Tale file batch permette di richiamare l’interprete Java (il cui nome è, appunto, java) con parametro dato dal nome della classe che contiene il metodo main (se non ancora non sapete cosa è, non preoccupatevi, lo capiremo molto presto…). Il parametro classpath serve per indicare uno o più percorsi in cui ricercare i file .class: nell’esempio trovate il mio percorso attuale che certamente differirà dal vostro.
Se nella vostra riga PATH dell’autoexec.bat non compare il percorso del file java.exe dovete inserire nel file batch di avvio del programma l’indirizzo completo del file. Ecco un esempio (indicativo solo della mia attuale configurazione)
Alcuni accorgimenti da attuare al file batch:
@echo off
java -classpath "C:\Documents and Settings\Davide\Desktop\articoli\Esempi articoli" HelloWorld
pause
La prima riga permette di non visualizzare i comandi effettuati ma solo l’esecuzione del programma, mentre l’ultima fa in modo che la finestra non si chiuda istantaneamente (utile nei casi in cui non vi siano inserimenti di dati da parte dell’utente e non vi sia GUI).
Concludiamo con un’osservazione: queste pagine non vogliono in alcun modo essere una guida completa ed esaustiva giacché questo richiederebbe molto più tempo e spazio. Speriamo invece che i nostri articoli risultino utili alle tante persone che desiderano avvicinarsi alla programmazione in Java in maniera semplice e, ci auguriamo, divertente.
Editor freeware: Jcreator
Per il testing di tutti i nostri esempi abbiamo impiegato l’ambiente freeware Jcreator, già descritto in precedenza.
Come premessa, ci preme sottolineare che non è assolutamente obbligatorio che adottiate il medesimo ambiente: tutti i principali ambienti di sviluppo compilano ed eseguono questi esempi, a patto che abbiate provveduto ad installare la JDK nella versione di riferimento 1.4.1, o comunque in una versione successiva a 1.2 (Java 2).
Come prima cosa diciamo che è consigliabile installare la JDK prima di installare l’ambiente Jcreator, poiché in questo modo al primo avvio del programma il wizard vi chiederà semplicemente di indicargli il percorso in cui è reperibile la JDK stessa.
Analogo discorso vale per l’utilissima documentazione.
Se invece non avete seguito questa procedura dopo aver installato la JDK andate in Configure , Options e scegliete JDK Profiles: vi si presenterà una mascherina come la seguente:
Cliccate su New ed indicate il percorso in cui avete installato la JDK. A questo punto siete veramente pronti per utilizzare l’ambiente Jcreator.
Fondamentalmente quello che dovete saper fare è compilare ed eseguire i vostri programmi. Per fare questo potete utilizzare oltre ai classici menù, le seguenti icone
rispettivamente per compilare ed eseguire il file corrente. Se però state lavorando ad un progetto che richieda un discreto numero di classi risulta conveniente fare riferimento alle icone poste a fianco:
Tali icone consentono, rispettivamente, di compilare tutti i file di progetto e di eseguire in automatico il listato contenente il metodo main.