martedì 18 novembre 2014

[JAVA] Iniziare la programmazione in Java


Per scrivere un programma in Java, non sempre si usa scriverlo interamente a mano: in genere si utilizza un IDE  che mette a disposizione i tool necessari affinché venga resa più facile la gestione dei file.
Scrivere a mano più essere istruttivo per creare il primo programma, per esempio questo:

package my.first.project;
public class Primo {
public static void main(String[] args) {
System.err.println("ciao mondo");
}
}

Si comincia copiando il codice in un file in un qualsiasi editor di testi. Salviamo e chiamiamo l’esempio PrimoProgramma.java, poi eseguiamo il compilatore:

javac PrimoProgramma.java

Il risultato sarà questo:

PrimoProgramma.java:3: error: class Primo is public, should be declared in a file named Primo.java
public class Primo {
^
1 error
Il compilatore ci avverte, quindi, del primo errore.


I nomi delle classi in Java, convenzioni

In Java infatti ogni classe pubblica (public class) deve essere contenuta in un file il cui nome sia identico al nome della classe stessa: ad esempio Classe dovrà stare nel file Classe.java e Primo dovrà quindi stare nel file Primo.java.

In generale si usa assegnare ad ogni classe il relativo file per convenzione, anche quando non è obbligatorio (se togliamo la keyword public e lasciamo solo class possiamo compilare il programmino senza errori). Si ritiene infatti che questa pratica aiuti ad una buona organizzazione del codice.

Prima di procedere a rinominare il file ed a fare la prova successiva vale la pena di soffermarsi alla scelta del nome della classe (che abbiamo chiamato Primo).

In Java le classi possono avere i nomi più disparati: primo, PRIMO, Primo123, primo_, e sarebbero stati tutti nomi validi  ma esiste una convenzione che prevede che i nomi delle classi inizino con un carattere maiuscolo, continuino con caratteri minuscoli e, se composti da più parole, siano capitalizzate le prime lettere di tutte le componenti (la scrittura di parole composte capitalizzando tutte le prime lettere è comunemente detta CamelCase).

Quindi se volessimo creare una classe che si chiami “prima classe del tutorial” la convenzione (non la sintassi) ci indicherebbe di chiamarla PrimaClasseDelTutorial (nei nomi delle classi la sintassi prevede che non si possano usare gli spazi).

Rinominiamo a questo punto PrimoProgramma.java in Primo.java e tentiamo ancora la compilazione:

javac Primo.java

Questa volta non otterremo nessun errore e, accanto al file Primo.java, troveremo un secondo file chiamato Primo.class. Il compilatore javac genererà dei files .class ogni volta che lo utilizzeremo su dei file .java.

Il file Primo.class contiene il bytecode del nostro programma java:

java Primo

Qui il nome “Primo” che passiamo come argomento dell’eseguibile java non si riferisce al nome del file .class, ma è proprio il nome della classe da eseguire.


Rispettare il namespace

L’esecuzione anche questa volta darà un risultato inatteso, che potrebbe essere un semplice:

Errore: impossibile trovare o caricare la classe principale Primo

L’errore è dovuto al fatto che la JVM cerca la nostra classe nella directory my/first/project/, cosa giustificata dal fatto che nel nostro programma la prima linea dice che la classe Primo appartiene al package my.first.project.

In fase di esecuzione la JVM si aspetta di trovare la classe in un directory che è formata dal nome del package dove i punti (‘.‘) sono sostituiti da slash (‘/‘).

Si crea la directory, si spostano entrambi i file e riproviamo:

mkdir -p my/first/project
mv Primo.* my/first/project/

e avremo (questa volta esattamente):

java my.first.project.Primo

Otteniamo quindi:

ciao mondo


Package e JAR

I package in Java sono il modo più naturale di raggruppare le classi in gruppi (moduli, unità, gruppi, categorie) in modo da rendere più leggibile il codice.
Come per i nomi le classi, Java lascia molta libertà allo sviluppatore nella scelta delle componenti di un package name. Tuttavia anche in questo caso una convenzione comunemente utilizzata è quella di utilizzare solo caratteri minuscoli ed eventualmente numeri.
Poiché il compilatore genererà sempre almeno un file .class da ogni file .java (da un singolo file .java possono essere generati anche più file .class), i programmi compilati in java potrebbero diventare rapidamente scomodi da gestire in quanto composti da intere directory di file.
Per questo motivo insieme al compilatore ed alla JVM viene fornito anche un altri eseguibile il cui nome è jar (java archiver) il cui scopo è esattamente quello di prendere una intera directory di class files e trasformarla in un unico file (detto java archive) più facile da maneggiare e gestire. Ad esempio:

jar cf primoprogramma.jar my

creerà il file primo programma.jar che contiene tutto l'albero di directory. Un archivio jar è la versione compressa della directory ed il formato di compressione è esattamente lo zip; per spacchettare un jar si può addirittura usare qualsiasi programma in grado di decomprimere gli zip; anche per crearlo potreste farlo ma in tal caso dovreste creare a mano il file MANIFEST.MF che trovate nella directory META-INF dell”archivio e che jar ha provveduto automaticamente a creare.

Per controllare il contenuto del file .jar possiamo eseguire:

jar tvf primoprogramma.jar


Classpath e jar

Quando vorremo utilizzare le classi compilate nel jar non avremo bisogno di decompimerlo ma potremo chiedere direttamente alla JVM di utilizzare come ‘classpath’ il file jar:

java -cp primoprogramma.jar my.first.project.Primo

Il classpath è sostanzialmente una sorta di filesystem virtuale dentro nel quale la JVM cerca le classi. Se il nostro programma fosse composto di più classi archiviate in più files jar avremmo potuto passarli tutti alla JVM concatenandoli:

java -cp primoprogramma.jar:secondo.jar my.first.project.Primo


Il main

Come ultima nota circa il nostro programmino di 6 righe (parentesi comprese) va osservato che il contenuto della classe è formato da un metodo chiamato main e dichiarato public estatic.
Il fatto che il metodo si chiami main non è assolutamente un caso: main è precisamente il nome che deve avere il metodo che vogliamo far eseguire per primo alla JVM quando viene lanciata. Non solo: main dovrà avere anche la stessa firma (signature, ovvero gli argomenti ed il valore di ritorno) che abbiamo utilizzato in Primo.
Il fatto che il metodo statico main ritorni int significa che sarà possibile restituire un intero al sistema operativo come risultato dell’esecuzione di un programma (questo valore di ritorno è solitamente considerato un modo per segnalare un eventuale errore se è diverso da zero) mentre l’argomento args di tipo String[] (array di stringhe) sta a significare che quel metodo potrà ricevere (dalla JVM e dal sistema operativo che la esegue) un numero arbitrario di argomenti di tipo stringa; se modificate il programma come segue potrete sperimentare questa caratteristica:

package my.first.project;

public class Primo { 

public static void main(String[] args) {

System.err.println("ciao " + args[0] + " !" );
}
}

Compiliamo l’esempio ed eseguiamolo il comando:

java my.first.project.Primo " Java Developer"

In questa ultima versione si può osservare come sia semplice concatenare stringhe in java utilizzando l’operatore ‘+‘, che tra numeri effettua la somma mentre tra le stringhe è (overloaded) usato con il significato di concatenare.

giovedì 6 novembre 2014

[JAVA] Installare JDK e tool di sviluppo


JDK

Gli strumenti principali che JDK (Java Development Kit) offre sono:

-  JVM, composto dalla macchina virtuale;
- Le librerie standard (che costituisco Java core API);
- il comando java che serve per far partire la JVM ed eseguire i programmi.

javac: è il compilatore, il cui compito è quello di trasformare il codice sorgente Java nel bytecode che sarà poi eseguito dalla macchine virtuale java (JVM)

JRE (Java Runtime Environment): Ambiente di runtime

Oltre a questi, altri tool per lo sviluppo, tra i quali:

jar: Java Archiver

javadoc: tool genera la documentazione in HTML del codice java a partire da commenti inseriti nei sorgenti stessi.

javap: Java Class File Disassembler, un tool per invertire il processo di compilazione.

javah: tool utilizzata per permettere l’utilizzo di codice scritto in C (codice nativo) da java.

appletviewer: Viewer per applet che consente di eseguirle senza l’utilizzo di un web browser.

jdb: java debugger.

Oracle, proprietaria del marchio Java, supporta il Java Development Kit su molteplici architetture e sistemi operativi: tutte le versioni di Windows da Vista a 8, le versioni di Windows Server a partire dalla 2008; Mac OS X Mountain Lion e Mavericks; Linux Oracle, RedHat, Suse, Ubuntu oltre a Solaris e Ubuntu su processori ARM.

Per scaricare la release corrente di Java Platform -JDK- 8 (attualmente la più recente), basta cliccare su questo link e cliccare su download e accettare i termini della licenza:



La procedura di installazione è totalmente automatica e sarà sufficiente accettare i default del sistema di installazione. Su Windows basta selezionare le componenti da installare e la scelta della path del JRE.



Subito dopo avrete installato tutti i tool necessari per sviluppare in Java.
Il wizard, una volta completata l’istallazione ci suggerisce di visitare il sito della piattaforma Java standard edition dove si possono trovare molti documenti e tutorial. 


Impostare le variabili d’ambiente (Windows/Linux )

Il compilatore (javac) per default non è nella path e quindi per testarlo bisogna cercarlo nella directory di installazione, ad esempio:

C:\Program Files\Java\jdk1.8.0\bin\

Per poterlo utilizzare bisogna includerlo nelle variabili di ambiente del sistema (PATH).


Impostare PATH su Windows

Per le versioni di Windows, si parte dal pannello di controllo (quello desktop nel caso di Windows 8) per andare poi nell'icona Sistema. Nella maschera che appare clicchiamo su Impostazioni di sistema avanzate.  Nella nuova maschera troveremo il pulsante Variabili d'ambiente che ci permetterà di accedere al pannello di modifica delle variabili di sistema.


Cercare adesso la varibile Path e aggiungere il percorso relativo all'installazione copiandolo tutto fino a [...]bin\.


Impostare PATH su Ubuntu

Su Ubuntu il procedimento è ancora più semplice: basta modificare il file .bashrc e aggiungere la riga:

export PATH=$PATH:{{percorso di Java}}

ad esempio:

export PATH=$PATH:/opt/jdk1.8.0/bin


Verificare l’installazione

Per verificare il successo dell'installazione, si esegue la macchina virtuale, ad esempio aprendo l’interprete dei comandi (o il terminale) e provando a lanciare il comando:

java -version


martedì 4 novembre 2014

[JAVA] Introduzione alla programmazione Java


Tra la fine degli anni ’80 e i primi anni ’90,  Java nasce come il linguaggio ‘OO’ di grande diffusione per eccellenza permettendo di rendere possibile una migliore rappresentazione all’interno dei programmi per rendere il codice più facilmente mantenibile ed estendibile.

Da strutturale/procedurale a OOP

Se volessimo costruire un programma per gestire  dei conti bancari, per ciascuno dei conti gestiti, dovremmo rappresentare lo stato (un nome, owner ed un importo, amount) e scrivere alcune procedure per modificarlo (funzioni, subroutine). Pensiamo ad operazioni come versamento e prelievo alle quali passare ogni volta tra gli argomenti la struttura conto su cui operare.

Con l’approccio OO nel medesimo programma potremo invece pensare di avere un tipo di oggetto, ad esempio chiamato Conto che contenga insieme:

- lo stato (fields, i campi dell’oggetto);
- le procedure per la sua gestione (methods, metodi).

Si agisce così nella stessa sezione del codice (classe), sia sullo stato, sia sul behavior.

L’integrazione dello stato e del behavior è chiamata encapsulation (incapsulamento) ed è la base di quella caratteristica della programmazione OO che viene chiamata information hiding che consiste nel mantenere interno a precise sezioni del codice l’accesso allo stato delle entità utilizzate.

È interessante osservare, che OOP è una metodologia ed uno stile di progettazione del software che, tranne in casi particolari, può essere impiegato indipendentemente dal linguaggio ma che risulta estremamente più facile da adottare se il linguaggio (come Java, C++ e altri) ne fornisce le primitive (come le classi in Java).

Classi e oggetti in Java

La classe viene definita come una collezione di uno o più oggetti contenenti un insieme uniforme di attributi e servizi, insieme ad una descrizione circa come creare nuovi elementi della classe stessa (Edward Yourdan).

Un oggetto è dotato di stato, behavior ed identità; la struttura ed il comportamento di oggetti simili sono definiti nelle loro classi comuni; i termini istanza ed oggetto sono intercambiabili (Grady Booch).

Una classe in Java si definisce con la keyword class, dove si osserva che:

- il corpo (dichiarazioni di variabili e metodi) della classe è racchiuso tra parentesi graffe;
- le linee sono terminate da punto-e-virgola (;);
- le linee che iniziano per doppio slash (//) sono commenti così come tutto quello che è racchiuso tra ‘/*‘ e ‘*/‘;
- il doppio asterisco all’inizio di un commento (/**) ha un significato speciale in relazione al comando javadoc che sarà introdotto in seguito e serve per la generazione di documentazione a partire dai commenti nel codice.

Qualificatori di visibilità

I qualificatori (public e private) determinano la visibilità degli elementi cui sono applicati:


Esistono altri 2 possibilità circa la visibilità:



Costruttore

Di particolare rilevanza è il metodo contrassegnato con il commento // costruttore: è diverso dagli altri metodi (versamento e prelievo) in quanto non dichiara un valore di ritorno e serve per creare nuove istanze di elementi di quella classe. Il costruttore delle classi deve essere utilizzato con la keyword new, la scrittura:

Conto myConto = new Conto("Portaletecnologico", 2.0e8);

In questo caso si vuole costruire una nuova istanza di un oggetto della categoria Conto ed inizializzarlo con owner “Portaletecnologico” e amount 2 miliardi.

Nel momento in cui non viene specificato nessun costruttore, nella definizione della classe ne avremmo dovuto creare uno di default senza argomenti. Si possono aggiungere quanti costruttori si vogliono a condizione che abbiano tutti diversa signature (firma). I costruttori devono avere il nome uguale a quello della classe.

this

All’interno del costruttore si può osservare anche l’uso della keyword this che in ciascuna classe rappresenta sempre l’istanza corrente.

Senza this l’assegnazione non avrebbe effetti in quanto significherebbe che si assegna il contenuto della variabile owner ad owner stessa, mentre con la qualificazione della variabile significa che stiamo assegnando il contenuto della variabile owner, che è stata passata come argomento al metodo, al field owner della classe Conto.

Notazione ‘.’

Una volta costruito l’oggetto conto sarà possibile utilizzare i suoi metodi con la notazione:

conto.versamento(10);
conto.prelievo(100);

L’accesso ai field può essere possibile con la medesima notation (e.g. conto.amount = 7) ma è proibito per scelta della nostra classe che definisce i field come private e quindi il compilatore ce lo segnalerebbe come errore.

Ereditarietà: estendere una classe

L’utilità della strutturazione OO diventa palese se si pensa a questo punto che potrebbe nascere la necessità di estendere l’immaginario programma per la gestione di conti con una banalizzazione di un conto in cui alcune somme vengano vincolate (e.g. nel tempo: sono nel conto ma disponibili solo dopo una certa data); in tal caso potremmo “estendere” direttamente la classe Conto.

Package

Ogni classe appartiene ad un package (dichiarato all’inizio del file in cui è definita una classe con la keyword package appunto) e serve a definire a qualche gruppo di classi essa appartiene.
Un package è del tutto simile ad un ‘path’ in un filesystem solo che al posto degli slash (/) le componenti sono separate da punti.