Sei sulla pagina 1di 58

Appunti_Java.12.

02--

Desantis Francesco

Appunti_Java.12.02

- 2 -

Desantis_Francesco
NOTAZIONE: i paragra evidenziati in verde contengono nozioni quasi esclusivamente teoriche; i paragra evidenziati in grigio contengono gli esempi di programmazione; tutto ci che non evidenziato, invece, tratta di commenti ai programmi o sono discorsi introduttivi a nuovi concetti. Struttura riassuntiva dal codice sorgente al programma eseguibile:

editor

sorgente java

compilatore

le class librerie

Java Virtual Machine J.V.M.

Esecuzione programma

Il compilatore Java non produce direttamente un codice eseguibile dal calcolatore, ma produce un codice indipendente dal particolare calcolatore denominato Java bytecode. Il bytecode viene interpretato dalla Java Virtual Machine (JVM). Per eseguire un programma Java compilato su una qualsiasi piattaforma sufficiente avere l'interprete per il Java bytecode. Questa indipendenza dalla piattaforma una delle caratteristiche che hanno portato ad una cos rapida diffusione di Java. Concetto di... Programmazione ad oggetti (OOP - Objet Oriented Programming): Java un linguaggio di programmazione ad alto livello (pi vicino al programmatore che al calcolatore) orientato agli oggetti. Nellorientamento ad oggetti lelemento di base diventa loggetto, quale interazione tra dato ed azione sul dato (metodo). Prima di addentrarci nella programmazione bene sapere il signicato di diversi termini: oggetto dato o attributo metodo funzione classe di oggetto servizi costruttori distruttori messaggi binding statico binding dinamico insieme di dati e metodi variabile procedura, ovvero un insieme di istruzioni che possono essere svolte pi volte senza doverle riscrivere istruzione, ovvero una parte di codice che compie unazione elementare insieme di oggetti con struttura e comportamento comuni azioni di un metodo metodi per aggiungere uno o pi oggetti in una classe metodi per togliere uno o pi oggetti in una classe richiesta inviata ad un oggetto per attivare uno dei suoi metodi quando laccesso alla classe destinataria del messaggio da luogo, qualora la richiesta sia corretta, allo sviluppo del codice opportuno gi in fase di compilazione quando il controllo circa il messaggio e il suo collegamento con la classe avvengono durante lesecuzione

Un linguaggio, per essere ad oggetti, deve possedere essenzialmente quattro caratteristiche:

- 3 -

Appunti_Java.12.02

incapsulamento

prerogativa essenziale degli oggetti, che devono nascondere al loro interno dati e metodi rendendo pubbliche verso lesterno solo le interfacce che ne permettono luso (dette messaggi)

ereditariet

consente ad un oggetto di derivare da un altro oggetto le sue caratteristiche (quindi i suoi dati e i suoi metodi) con la possibilit di denirne altre (specializzazione). Ipotizzando che b sia una classe derivata dalla classe a, allora b si dice sottoclasse di a e a si dice superclasse di b

polimorsmo

la caratteristica grazie alla quale viene realizzata la essibilit maggiore degli oggetti, per cui certe scelte sono realizzate automaticamente dal sistema e non dal programmatore

comunicazione tra oggetti

modo attraverso cui un programma viene realizzato non pi come unastrazione procedurale del funzionamento di un calcolatore, ma come uninterazione continua tra oggetti

Per realizzare i programmi proposti si consiglia di utilizzare il compilatore Eclipse, scaricabile gratuitamente da The Eclipse Foundation open source community web site nellarea Downloads cliccando sulla voce Eclipse Classic e scegliendo la versione adatta al proprio sistema operativo. Piccola serie di comandi utili
// Commento riga /* Commento paragrafo*/ import java.lang.*; // importa librerie predefinite di java (pu anche essere omessa)

public static void main (String [] args) { // dichiarazione del metodo principale (main) cio il metodo da cui il compilatore inizia l'esecuzione import javax.swing.JOptionPane; // importa i comandi della classe JOptionPane (utilizzo di finestre di dialogo) della libreria swing import java.io.*; // importa librerie per la gestione dellin-put/out-put

Primo esempio di programma


import java.lang.*;

- 4 -

Desantis_Francesco

public }

class primo { public static void main (String[]args) { System.out.println("Ciao a tutti!!!"); }

Non fa altro che stampare a schermo la frase ciao a tutti. Con il .println("...") sposta il cursore a capo, cosa che non accade con l'utilizzo di .print("..."); Sintassi intestazione metodi: public/private static/NonStatico TipoRisultato NomeMetodo (parametri) Modificare stringhe (comando toUpperCase)
public class public } maiuscolo { static void main (String[]args) { System.out.println("Parola".toUpperCase()); }

Scrive la stringa passatagli come parametro a lettere maiuscole (stampa 'PAROLA'). Al contrario .toLowerCase() scrive la stringa passatagli come parametro a lettere minuscole (stampa 'parola'). Concetto di... Variabile: una variabile non altro che una parte di memoria, pi o meno grande, in cui il programmatore decide cosa inserire. In pratica va vista come un semplice contenitore in cui si possono inserire e togliere a nostro piacimento elementi vari. All'interno della variabile si possono inserire solo dati dello stesso tipo (ad esempio una variabile di tipo String potr contenere solo parole o frasi). Per prendere dimestichezza con i comandi principali utilizzeremo solo variabili di tipo String. Differenza tra i modicatori public e private: - public indica che il metodo o la variabile di istanza utilizzabile anche allesterno della classe in cui si trova; - private indica che il metodo o la variabile di istanza utilizzabile soltanto allinterno della classe in cui si trova. Variabili distanza: - denita dentro la classe, fuori da ogni metodo; - preceduta da un modicatore di accesso (di solito private); - viene inizializzata, implicitamente a valori di dafault o esplicitamente dal costruttore allatto della creazione delloggetto. OSSERVAZIONE: le variabili di istanza sono associate ai singoli oggetti e non allintera classe, cio ogni oggetto ha le sue variabili di istanza. Due oggetti distinti hanno variabili di istanza distinte.

- 5 -

Appunti_Java.12.02
Concatenazione di stringhe (comando concat)
public class public } unione { static void main (String[]args) { String a = "Ciao"; String b = "Hello"; System.out.println(a.concat(b)); }

Unisce le due stringhe 'a','b' quindi stampa a schermo 'CiaoHello'. Lo stesso risultato lo si poteva ottenere anche non dichiarando le 2 variabili: bastava scrivere System.out.println ("Ciao".concat("Hello")); . Oppure si poteva omettere il .concat ed utilizzare solamente il + ovvero System.out.println (a + b); quindi anche System.out.println ("Ciao" + "Hello"); .

Assegnazione
public } class assegnazione { public static void main (String[]args) { String a = "Franc"; String b b = "esco"; a = b; System.out.println(a) }

Si effettuano 3 assegnazioni. La prima assegna il valore 'Franc' alla variabile 'a' di tipo String; la seconda assegna il valore 'esco' alla variabile 'b' di tipo String dichiarata precedentemente; la terza assegna alla variabile 'a' il contenuto della variabile 'b' ('esco'). Comunica a schermo il valore contenuto nella variabile a, quindi esco. Si pu anche convertire in lettere maiuscole o minuscole il valore assegnato alle strighe gi al momento della dichiarazione:
String a = "Franc".toUpperCase(); oppure String a = "Franc".toLowerCase(); .

Parti di Stringhe (comando substring)

- 6 -

Desantis_Francesco

public class parti { public static void main (String[]args) { String a = "Francesco"; String prima; String dopo; prima = a.substring(0,3); // prime 3 lettere della variabile a dopo = a.substring(4) // lettere dalla 5 in poi System.out.println(prima); System.out.print(dopo); } }

Alla variabile 'prima' si assegnano le lettere di posto compreso tra i numeri riportati tra parentesi (le prime 3 lettere della variabile 'a' ('Fra')), mentre alla variabile 'dopo' si assegnano tutte le lettere della variabile 'a' a partire dalla 5^ ('cesco'). In altre parole, il comando stringa1 = stringa2.substring(n,m) mette nella variabile stringa1 tutti quei caratteri ( n < caratteri m ) di stringa2; invece, il comando stringa1 = stringa2.substring(n) mette nella variabile stringa1 tutti quei caratteri ( caratteri < n ) di stringa2. Stampa a schermo 'Fracesco'. Oggetti mutabili (classe StringBuffer)
public class SideEffect1 { public static void main (String [] args) { StringBuffer s = new StringBuffer("Ciao"); StringBuffer t; t = s; s.append("!"); System.out.println(s.toString()); System.out.println(t.toString()); } }

Stampa a schermo due volte 'Ciao!'. Con questo programma si dimostrato che per utilizzare variabili di tipo StringBuffer necessario inserire un costruttore (new). La particolarit delle variabili di tipo StringBuffer che possono essere modificate direttamente. Input da tastiera (metodo predefinito showInputDialog della classe JOptionPane della libreria swing)
import javax.swing.JOptionPane; public class input { public static void main (String[]args) {

- 7 -

Appunti_Java.12.02
} } String nome = JOptionPane.showInputDialog("Inserire nome"); JOptionPane.showMessageDialog (null,"Arrivederci sign. "+ nome); System.exit(0);

Dopo aver importato la classe JOptionPane della libreria javax.swing,nel metodo principale si assegna alla stringa 'nome' ci che l'utente digiter all'interno della finestra di dialogo .showInputDialog . Attraverso un'altra finestra di dialogo .showMessageDialog, il programma saluter l'utente con una frase di arrivederci seguita dal nome precedentemente immesso. OSSERVAZIONE: Il null passato come primo parametro al metodo indica che la nestra da creare non una sottonestra di una nestra gi esistente. OSSERVAZIONE: Il comando System.exit(0); deve essere aggiunto al metodo main dei programmi che usano la classe predenita JOptionPane perch le nestre di dialogo non sono gestite direttamente dal main e quindi bisogna dare loro un esplicito comando di terminazione. Concetto di Modularizzazione: - il programma deve essere strutturato in parti autonome dette moduli; - i vari moduli devono essere legati tra loro attraverso relazioni precise. Concetto di Astrazione: - si costruisce un modello astratto del problema su cui individuare la soluzione (ci si focalizza sugli aspetti essenziali del problema; si ignorano aspetti non rilevanti rispetto all'obbiettivo); - si sceglie un modello concreto corrispondente al modello astratto e utilizzando questo si realizza la soluzione specifica. Tipi di astrazione: - sulle operazioni; - sugli oggetti. Istruzione return: se un metodo deve restituire un risultato, allora esso deve contenere l'istruzione return, la quale, termina il metodo e restituisce il risultato dello stesso al modulo cliente (la parte di programma dove stato invocato il metodo stesso). Istruzione return
} public static String saluto (String nome, String cognome) { return "Buon giorno " + nome + " " + cognome + "!";

Ipotizzando che i parametri nome e cognome contenessero rispettivamente 'Francesco' e 'Desantis', allora il metodo 'saluto' restituir come risultato ad un eventuale metodo cliente una stringa contenente la frase 'Buon giorno Francesco Desantis!'. OSSERVAZIONE: lespressione che segue listruzione return deve essere compatibile con il TipoRisultato (vedere Sintassi intestazione metodi p.5) presente nellinvocazione del metodo (in questo caso si invoca il metodo chiamato 'saluto' il quale deve restituire un risultato di tipo String: non a caso l'istruzione return seguita da un'espressione di tipo String 'Buon giorno Francesco Desantis!).

- 8 -

Desantis_Francesco

Uso dei metodi statici definiti nella stessa classe (richiamare metodi della stessa classe)
import javax.swing.JOptionPane; public } class StessaClasse { public static void StampaSaluto() { System.out.println("Buon giorno!!!"); } public static void StampaSalutoPersonale (String nome, String cogn) { System.out.println("Buon giorno " + nome + " " + cogn+ "!"); } public static void StampaSalutoInformale (String nome) { System.out.println ("Ciao " + nome + "!"); } public static String SalutoPersonale (String nome, String cogn) { return "Buon giorno " + nome + " " + cogn + "!"; } public } static void main (String[] args) { StampaSaluto(); String n = JOptionPane.showInputDialog("Nome"); String c = JOptionPane.showInputDialog("Cognome"); StampaSalutoPersonale(n,c); StampaSalutoInformale(n); JOptionPane.showMessageDialog(null,SalutoPersonale(n,c)); System.exit(0);

Partendo sempre dal metodo principale main: Viene richiamato il metodo 'StampaSaluto' senza alcun passaggio di parametri. Stampa a schermo la stringa 'Buon giorno !!!'; Vengono dichiarate 2 variabili (n,c) di tipo String che andranno a contenere rispettivamente il nome e il cognome che l'utente inserir tramite la finestra di dialogo (.showInputDialog); Viene richiamato il metodo 'StampaSalutoPersonale' con le stringhe n,c (contenenti il nome e il cognome inseriti dall'utente) passate come parametro. A questo punto ci che contenuto in 'n' va in nome e ci che contenuto in 'c' va in cogn. Di conseguenza il metodo invocato stamper a schermo 'Buon giorno ' seguito dal nome e cognome inseriti dall'utente. Viene richiamato il metodo 'StampaSalutoInformale' con l'unica stringa n (contenente il nome inserito dall'utente) passata come parametro. A questo punto ci che contenuto in 'n' va in nome. Ne segue che il metodo avr come risultato (return) una stringa del tipo "Buon giorno" seguita dal solo nome inserito dall'utente.

- 9 -

Appunti_Java.12.02
Viene richiamato il metodo 'SalutoPersonale' con ancora una volta le 2 stringhe 'n' e 'c' passate come parametro. Il metodo invocato ritorner con una stringa del tipo "Buon giorno" seguita dal nome e dal cognome che per verr visualizzata attraverso una finestra di dialogo (.showMessageDialog). Chiusura delle finestre di dialogo. Uso dei metodi statici definiti in un'altra classe (richiamare metodi da un'altra classe): Il meccanismo appena descritto (richiamo di metodi) applicabile anche tra metodi che non si trovano tutti nella stessa classe. Creiamo quindi, utilizzando l'esempio precedente, una classe che raggruppi tutti i metodi che vengono richiamati (metodi fornitori), avremo: Classe formata esclusivamente da metodi fornitori
public } class Saluti { public static void StampaSaluto() { System.out.println("Buon giorno!!!"); } public static void StampaSalutoPersonale (String nome, String cogn) { System.out.println("Buon giorno " + nome + " " + cogn+ "!"); } public static void StampaSalutoInformale (String nome) { System.out.println ("Ciao " + nome + "!"); } public static String SalutoPersonale (String nome, String cogn) { return "Buon giorno " + nome + " " + cogn + "!"; }

Questa classe se mandata in esecuzione non fornir nessun risultato in quanto manca il metodo principale main. Ora creiamo un altra classe con il metodo cliente main che richiama i metodi fornitori, per cui avremo: Metodo cliente
import javax.swing.JOptionPane; public class Cliente{ public static void main (String[] args) { Saluti.StampaSaluto(); String n = JOptionPane.showInputDialog("Nome"); String c = JOptionPane.showInputDialog("Cognome"); Saluti.StampaSalutoPersonale(n,c); Saluti.StampaSalutoInformale(n);

- 10 -

Desantis_Francesco
} } JOptionPane.showMessageDialog(null,Saluti.SalutoPersonale(n,c)); System.exit(0);

Il risultato praticamente lo stesso, per questa volta stato raggiunto in una maniera diversa. Analizzati questi ultimi esempi sar chiaro che: - nel caso in cui il metodo cliente si trovi nella stessa classe del metodo fornitore allora, per richiamarlo, basta semplicemente inserire all'interno del metodo cliente il nome del metodo fornitore seguito da eventuali parametri messi tra parentesi; - mentre, se i metodi cliente e fornitore si trovano in classi diverse, per richiamare il fornitore si dovr inserire allo stesso modo nel metodo cliente il nome del metodo fornitore preceduto per dalla classe cui appartiene il fornitore e come sempre seguito da eventuali parametri messi tra parentesi. Concetto di... Passaggio dei parametri: Bisogna distingue 2 tipi di parametri: - parametri Attuali : sono quelli presenti nell'invocazione di un metodo;
StampaSalutoPersonale(n,c); // viene invocato il metodo 'StampaSalutoPersonale' con n,c parametri ATTUALI // intestazione del metodo 'StampaSalutoPersonale' con nome, cogn parametri FORMALI

- parametri Formali : sono quelli presenti nell'intestazione di un metodo.


public static void StampaSalutoPersonale (String nome, String cogn)

Java prevede un solo modo per legare gli attuali con i formali, il legame per valore, che consiste: - valutare il parametro attuale; - associare una locazione di memoria al parametro formale; - inizializzare tale locazione con il valore del parametro formale. Non deve esser dato per scontato che i parametri formali e attuali devo essere tra loro compatibili, cio dello stesso tipo (sia n,c che nome e cogn sono di tipo String) e che bisogna esser coerenti con l'ordine con cui si inseriscono (siano n, c parametri attuali e nome, cogn parametri formali, ci che contenuto in n andr in nome perch entrambi inseriti per primi, a sua volta ci che contenuto in c andr in cogn perch entrambi inseriti per secondi). Riettiamo sul seguente esempio: Modica di un oggetto da parte di un metodo
public class ModificaOggetto { public static void CambiaValoreAA (String aa) { aa = aa + "!"; } public static void CambiaValoreBB (StringBuffer bb) { bb.append("!"); } public static void main (String[] args) {

- 11 -

Appunti_Java.12.02
} } String a = "Ciao"; StringBuffer b = new StringBuffer("Hello"); System.out.println("La stringa a contiene : " + a); System.out.println("La stringa buffer b contiene : " + b); CambiaValoreAA(a); CambiaValoreBB(b); System.out.println("La stringa a contiene : " + a); System.out.println("La stringa buffer b contiene : " + b);

Stampa a schermo: La stringa a contiene : Ciao


La stringa buffer b contiene : Hello La stringa a contiene : Ciao La stringa buffer b contiene : Hello!

Il motivo per cui il valore della variabile b cambiato mentre quello della variabile a rimasto invariato non conseguenza diretta del passaggio dei parametri (che identico in tutte e due le invocazione ai metodi), ma dipende dal fatto che il metodo append (applicabile a variabili di tipo StringBuffer) va direttamente a modicare il valore della variabile. Praticamente, anche se entrambi i metodi CambiaValoreBB e CambiaValoreAA restituisco un risultato di tipo void , il valore della variabile b cambia lo stesso per il motivo prima spiegato. Concetto di... Campo dazione e tempo di vita di una variabile: - Campo dazione di una variabile: linsieme delle unicit di programma in cui la variabile visibile cio accessibile ed utilizzabile. - Tempo di vita di una variabile: il tempo in cui la variabile rimane effettivamente accessibile in memoria durante lesecuzione. Campo dazione delle variabili
public class CampoAzione { public static String copia (String s) { String t = s + s; return t; } public static void stampa1() { System.out.println( t ); } public static void stampa2() { System.out.println( a ); }

- 12 -

Desantis_Francesco

public }

static void main (String[]args) { String a = "Ciao"; a = copia(a); stampa1(); stampa2(); System.out.println(a);

Il programma non funzioner correttamente a causa di 2 errori (evidenziati in rosso): - nel metodo stampa1 la variabile t non visibile perch denita nel metodo copia; - nel metodo stampa1 la variabile a non visibile perch denita nel metodo main. Denizione di una classe
// Metodi fornitori public class Persona { } private String nome; private String residenza; public String getNome() { return nome; } public String getResidenza() { return residenza; } public String setResidenza(String NuovaResidenza) { residenza = NuovaResidenza; return residenza; }

In questo modo stata denita una classe di nome persona avente nome e residenza come variabili di istanza e 2 metodi che vanno a descrivere gli elementi della classe persona. In questo caso una Persona avr un nome e una residenza. Per convenzione i metodi che formano gli elementi sono preceduti dal get (getNome e getResidenza). Se si ha la necessit di dover modicare qualche elemento della classe si dovr aggiungere un altro metodo chiamato allo stesso modo per preceduto dal set. In questo esempio si pu modicare solo lelemento inerente alla residenza della persona infatti stato inserito un ulteriore metodo chiamato setResidenza.

- 13 -

Appunti_Java.12.02
Praticamente, denire una classe vuol dire creare un modellino che descriver quelle che sono le caratteristiche di ogni oggetto che apparterr a quella classe. Uso di una classe denita
// Metodo cliente private class public } } ClientePersona { static void main (String[]args) { Persona p1 p1 = new Persona(); p1.setResidenza("Roma"); System.out.println(p1.getResidenza());

// // // //

1 2 3 4

Questo esempio un continuo del precedente. Qui stata denita una nuova classe contenente il metodo main che funge da cliente per la classe Persona. In dettaglio: // 1 : denisce un oggetto di classe Persona (viene denito solo il nome delloggetto); // 2 : il COSTRUTTORE crea loggetto p1 precedentemente denito; // 3 : richiama il metodo che permette la modica di un elemento delloggetto (in questo caso la residenza) e passa la stringa ("Roma") come parametro; // 4 : stampa la residenza della persona p1 appartenente alla classe Persona; quindi stampa Roma perch modicata in //3; Praticamente stato creato un oggetto chiamato p1 su modello della classe Persona. Overloading
public class saluto { } public static void StampaSaluto() { System.out.println("Ciao"); } public static void StampaSaluto (String nome) { System.out.println ("Ciao " + nome); }

Questo programma serve a sottolineare unaltra caratteristica di java, ovvero che si possono chiamare diversi metodi con lo stesso nome limportante che abbiano un diverso numero di parametri (Overloading). Parametro formale this: tipicamente viene usato quando, in caso di omonimia delle variabili di istanza e delle variabili o dei parametri formali dichiarati nel metodo, si vuole distinguere una variabile di istanza da una variabile locale. Pu essere utilizzato solo in metodi non statici.

- 14 -

Desantis_Francesco
Parametro formale this
public class Persona { private String nome; private String residenza; } public String getNome() { return nome; } public } String getResidenza(){ String residenza; residenza = this.residenza; // this.residenza riferito a var_istanza2 return residenza;

// var_istanza1 // var_istanza2

public void setResidenza(String residenza) { this.residenza = residenza; // this.residenza riferito a var_istanza2 return this.residenza }

Si toccato con mano, quindi, ci che stato precedentemente spiegato a riguardo del parametro this. A questo punto, con le conoscenze che si possiedono si pu realizzare un programma un po pi corposo immaginando di dover rappresentare 2 automobili. Ogni automobile avr una targa, un modello, un colore e anche un proprietario. Del proprietario si vuole conoscere, oltre al nome, anche la residenza. Il programma deve includere dei metodi che vanno a cambiare il colore e il proprietario dellautomobile e stampino a schermo i cambiamenti apportati alle automobili (colore e proprietario). Da dove iniziare? Come primo passo bisogna creare la classe Persona a cui apparter il proprietario dellautomobile: Denizione della classe fornitore Persona
public class Persona { private String nome; private String residenza; // rappresentazione degli oggetti // // // // costruttore

public Persona (String n, String r) { nome = n; residenza = r; }

- 15 -

Appunti_Java.12.02
} public String getNome() { return nome; } // metodo pubblico

public String getResidenza() { return residenza; }

// metodo pubblico

Questa soltanto una classe che va a denire quelli che sono gli elementi del proprietario di unautomobile. Al secondo passo bisogna fare ci che stato fatto nel primo, per andando a denire gli elementi di unautomobile richiesti nel testo del problema, quindi: Denizione della classe fornitore Auto
public class Auto { private private private private public } String targa; String modello; String colore; Persona proprietario; // rappresentazione degli oggetti // // // // // // //

Auto (String t, String m, String c) { // costruttore targa = t; modello = m; colore = c; proprietario = null; // si pu benissimo anche omettere

public String getTarga() { return targa; } public String getModello() { return modello; } public String getColore() { return colore; }

// metodo pubblico

// metodo pubblico

// metodo pubblico

public Persona getProprietario() {

// metodo pubblico

- 16 -

Desantis_Francesco
} } return proprietario;

public void setColore(String NuovoColore) { colore = NuovoColore; }

// metodo pubblico

public void setProprietario(Persona NuovoProprietario) { proprietario = NuovoProprietario; }

// metodo pubblico

Anche questa soltanto una classe che va a denire quelli che sono gli elementi di unautomobile. Ora si deciso di creare una classe cliente per la classe auto in cui sono contenuti i metodi che permetteranno il cambiamento del colore e del proprietario di unautomobile, quindi: Cliente per la classe Auto
public class Servizi { } public static void CambiaColore (Auto a, String colore) { a.setColore(colore); } public static void CambiaProprietario (Auto a, Persona prop) { a.setProprietario(prop); }

Per nire si realizza lultima classe che unisce un p tutto ci che stato fatto in precedenza esaudendo le richieste del quesito proposto, quindi: Classe principale del programma
public class Principale { private static void StampaDatiAuto (Auto a) { System.out.println("Targa = " + a.getTarga()); System.out.println("Modello = " + a.getModello()); System.out.println("Colore = " + a.getColore());

- 17 -

Appunti_Java.12.02
} } private static void StampaDatiProprietario (Auto a) { System.out.println ("Nome proprietario = " + a.getProprietario().getNome()); System.out.println ("Residenza proprietario = " + a.getProprietario().getResidenza()); } public static void main (String[] args) { } Auto a = new Auto ("aaa", "Fiat 500", "Rosso-Nero"); StampaDatiAuto(a); System.out.println("----------------------------------------------"); Persona p1 = new Persona ("Francesco" , "Bassano Romano"); a.setProprietario(p1); StampaDatiProprietario(a); System.out.println("----------------------------------------------"); Servizi.CambiaColore(a, "Bianco-Nero"); StampaDatiAuto(a); System.out.println("----------------------------------------------"); Auto b = new Auto ("bbb", "Aston Martin", "Nerolucido"); StampaDatiAuto(b); System.out.println("----------------------------------------------"); Persona p2 = new Persona ("Giovanni", "Blera"); b.setProprietario(p2); StampaDatiProprietario(b); System.out.println("----------------------------------------------"); Persona p3 = new Persona ("Michele", "Artena"); Servizi.CambiaProprietario(b,p3); StampaDatiProprietario(b);

Osservando bene il programma possiamo intuire che comunicher a schermo:


Targa = aaa Modello = Fiat 500 Colore = Rosso-Nero ---------------------------------------------Nome proprietario = Francesco Residenza proprietario = Bassano Romano

- 18 -

Desantis_Francesco
---------------------------------------------Targa = aaa Modello = Fiat 500 Colore = Bianco-Nero ---------------------------------------------Targa = bbb Modello = Aston Martin Colore = Nerolucido ---------------------------------------------Nome proprietario = Giovanni Residenza proprietario = Blera ---------------------------------------------Nome proprietario = Michele Residenza proprietario = Artena

Praticamente alla Fiat 500 stato cambiato colore mentre alla Aston Martin stato cambiato il proprietario. Ereditariet: questo concetto gi stato affrontato a pag.1 ed ora si potr comprendere meglio il suo signicato attraverso un esempio pratico. Supponiamo che Studente sia una classe derivata da persona: Denizione della classe Persona
public class Persona { } private String nome; private String residenza; // rappresentazione degli oggetti // // // // costruttore

public Persona (String n, String r) { nome = n; residenza = r; } public String getNome() { return nome; }

// metodo pubblico

public String getResidenza() { return residenza; }

// metodo pubblico

- 19 -

Appunti_Java.12.02

Denizione della classe Studente: costruttore di una classe derivata (uso si super)
public class Studente extends Persona { } private String facolta; // variabili distanza

public Studente(String n, String r, String f) { // costruttore super (n,r); // invoca il costruttore Persona facolta = f; } public void StampaNome() { System.out.println(this.getNome()); } // in una sottoclasse si pu aggiungere uno o pi metodi appartenenti alla supercalsse

// si possono aggiungere anche altri metodi

Per fare in modo che una classe derivi da unaltra bisogna utilizzare un altro comando: il super. Esso serve semplicemente, in questo caso, ad evidenziare il fatto che le variabili n ed r si riferiscono alla superclasse Persona. Come gi detto , tutti gli oggetti della classe Studente, oltre ad avere i metodi e le variabili di istanza propri di Studente, ereditano tutti i metodi e le variabili di istanza di Persona, quindi in Persona sono ammesse istruzioni tipo:
Persona p = new Persona ("Francesco", "Roma"); Studente s = new Studente ("Jacopo", "Roma", "Ingegneria"); System.out.println(s.getResidenza);

Compatibilit: rimanendo sempre in ambito di classi derivate, c da aggiungere che gli oggetti della classe derivata sono compatibili con gli oggetti della classe base ma non vale il viceversa, infatti: Compatibilit
public class Compatibilita { public static void main (String[] args) { Persona p = new Persona ("Daniele", "Roma"); Studente s = new Studente ("Serafino", "Viterbo", "Ingegneria"); Persona pp;

- 20 -

Desantis_Francesco
} } Studente ss; pp = s; ss = p; // Errore! Persona non compatibile con Studente System.out.println(pp.getNome()); System.out.println(pp.getResidenza()); System.out.println(pp.getFacolt()); // Errore! getFacolt non un metodo di persona

Classe Object e metodo standard toString: bisogna sapere che tutte le classi denite in Java sono sottoclassi della classe predenita Object anche se un aspetto non indicato esplicitamente. Questo signica che tutte le classi ereditano da Object una serie di metodi standard tipo il toString. Questo metodo serve per trasformare un oggetto in una stringa. Tipicamente lo si usa per costruire una stringa con le informazioni stampabili di un oggetto. Ovviamente se lo si vuole utilizzare deve essere ridenito nella classe in cui servir. Ad esempio, ridenendolo nella classe persona facendo in modo che restituisca il nome della persona, avremo: Denizione del metodo standard toString della classe predenita Object:
public class Persona { } private String nome; private String residenza; // rappresentazione degli oggetti // // // // costruttore

public Persona (String n, String r) { nome = n; residenza = r; } public String toString() { return nome; return residenza; } public String getNome() { return nome; }

// definizione del metodo toString

// metodo pubblico

public String getResidenza() { return residenza; }

// metodo pubblico

- 21 -

Appunti_Java.12.02

Utilizzo del metodo standard toString della classe predenita Object:


public class ProvaToString { Persona p = new Persona ("Francesco", "Bassano"); System.out.println(p); // stamper nome e residenza dell'oggetto p perch equivale a System.out.println(p.toString()); }

Tipi di dato primitivi numerici: no a questo momento sono stati svolti esempi in cui guravano solo dati di tipo letterale, cio di tipo String. Per trattare le informazioni di tipo numerico, Java usa 6 diversi tipi di dato primitivi numerici: int, byte, double, long, short, float. Le loro caratteristiche sono: Dimensione 32 bit = 4 byte Dominio numeri interi compresi nellintervallo [ -231 ; 231 -1 ] + int Integer

somma sottrazione prodotto divisione intera resto della divisione intera

Operazioni possibili

* / %

Letterali Dimensione 8 bit = 1 byte Dominio numeri interi compresi nellintervallo [ -27 ; 27 -1 ] = [ -128 ; 128 ] + byte Operazioni possibili * / % Letterali Dimensione 16 bit = 2 byte Dominio numeri interi compresi nellintervallo [ -215 ; 215-1 ] = [ -32768 ; 32767 ] somma sottrazione prodotto divisione intera resto della divisione intera

- 22 -

Desantis_Francesco
+ short Operazioni possibili * / % Letterali Dimensione 64 bit = 8 byte Dominio numeri interi compresi nellintervallo [ -263 ; 263 -1 ] + long Operazioni possibili * / % somma sottrazione prodotto divisione intera resto della divisione intera somma sottrazione prodotto divisione intera resto della divisione intera

Letterali sequenze di cifre terminate con una L che denotano valori del dominio Dimensione 32 bit = 4 byte Dominio 232 numeri reali positivi e negativi con precisione di 7 cifre decimali [ 1.4012985 * 10-38 ; 3.4028235 * 10+38 ] + float Operazioni possibili * / somma sottrazione prodotto divisione intera

Letterali sequenze di cifre terminate con una F che denotano valori del dominio Dimensione 64 bit = 8 byte Dominio 264 numeri reali positivi e negativi con precisione di 15 cifre decimali [ 1.79769313486231570 * 10-308 ; 2.250738585072014 * 10+308 ] + Operazioni possibili somma sottrazione

double

- 23 -

Appunti_Java.12.02
double Operazioni possibili * / prodotto divisione intera

Letterali sequenze di cifre con un punto decimale, opzionalmente terminante con una D che denotano valori del dominio Tutti i concetti tipo lassegnazione, il passaggio dei parametri, ecc visti n ora valgono anche per i dati di tipo numerico; per bisogna fare delle accortezze: InPut da tastiera di un valore numerico (comando Integer.parseInt(...);)
import javax.swing.JOptionPane; public } class InPutNumero { public static void main (String[]args){ // Metodo per inserire da tastiera un int int a = Integer.parseInt(JOptionPane.showInputDialog("Inserisci numero")); } // Metodo equivalente String b = JOptionPane.showInputDialog("Inserisci numero"); int c = Integer.parseInt(b); JOptionPane.showMessageDialog(null, a); JOptionPane.showMessageDialog(null, c); System.exit(0);

Prima di utilizzare un valore numerico inserito da tastiera bisogna effettuare qualche passaggio in pi, ovvero bisogna convertire la stringa inserita con il JOptionPane.showInputDialog("...") in un int richiamando la sua classe dappartenenza seguita dal comando .parseInt quindi: Integer.parseInt(...); // tipo int di classe Integer Un discorso analogo vale anche per gli altri tipi di dato primitivi numerici, quindi: Byte.parseByte(...); // tipo byte di classe Byte
Short.parseShort(...); // tipo short di classe Short Long.parseLong(...); // tipo long di classe Long Float.parseFloat(...); // tipo float di classe Float Double.parseDouble(...); // tipo double di classe Double

Bisogna prendere in considerazione anche il comportamento delle seguenti istruzioni:

- 24 -

Desantis_Francesco

System.out.println(3 + 4); System.out.println("3" + 4);

// Stampa a schermo 7 // Stampa a schermo 34 perch avviene una conversione automatica

Concetto di... Overow numerico: poich linsieme dei valori rappresentabili mediante un tipo primitivo limitato ad un dato intervallo, applicando operatori aritmetici a valori di un dato tipo si potrebbe avere un overow nel caso in cui il risultato delloperazione non possa essere rappresentato mediante il tipo stesso, ad esempio: int a = 2147483647; // massimo valore rappresentabile con il tipo int
int b = a + 1; System.out.println(b); // causa un overflow // cosa stamper???

Incrementando il valore massimo che il tipo int pu raggiungere si genera un overow e, in questo caso, si avr a schermo il valore -2147483648 ovvero il valore pi piccolo che si pu rappresentare con il tipo int. In altre parole un p come se si fosse effettuato il ciclo dei valori rappresentabili. Operatori di assegnazione composta: questo concetto riassumibile in un esempio:
int int x = x = x = x = x = x = 6; y = 2; x x x x x + * / % y; y; y; y; y; // // // // // oppure oppure oppure oppure oppure x x x x x += -= *= /= %= y y y y y

Il succo del discorso che se vogliamo sostituire il contenuto di una variabile di tipo int con un valore ottenuto facendo unoperazione in cui uno degli elementi rappresenta proprio il valore contenuto nella variabile stessa, allora Java, oltre al metodo tradizionale (scritto in nero), offre un metodo alternativo pi rapido (scritto come commento in verde). E di immediata intuizione che in questo modo si pu anche abbreviare lincremento/decremento di una variabile mettendo, nel precedente esempio, 1 al posto di y, quindi: x = x + 1; // oppure x += 1; oppure x++;
x = x - 1; // oppure x -= 1; oppure x--;

Nel caso in cui si effettuano operazioni con elementi numerici di tipo diverso, di che tipo il risultato? Per rispondere a questa domanda si deve consultare la seguente tabella che riporta tutti i casi possibili di unoperazione tipo a + b:
b byte short int long float double

- 25 -

Appunti_Java.12.02

byte short a int long float double

int int int long float double

int int int long float double

int int int long float double

long long long long float double

float float float float float double

double double double double double double

E sempre possibile assegnare un valore numerico di una variabile ad unaltra variabile di un altro tipo? Anche qui per rispondere a questa domanda bisogna consultare la seguente tabella che riporta tutti i casi possibili di unassegnazione del tipo a = b:
b byte byte short a int long float double short int long float double

Ok Ok Ok Ok Ok Ok

Errore Ok Ok Ok Ok Ok

Errore Errore Ok Ok Ok Ok

Errore Errore Errore Ok Ok Ok

Errore Errore Errore Errore Ok Ok

Errore Errore Errore Errore Errore Ok

Conversione esplicita cast: ipotizzando che in un programma non si pu assolutamente evitare di assegnare, ad esempio, un long ad un int (commettendo quindi un errore di assegnazione), come si procede? Si procede con la conversione esplicita cast:

int i; long l; l = (long)i; System.out.println(l);

Allo stesso tempo per si pu incappare in situazioni tipo:

int a = (int)3.568; System.out.println(a); // stampa il valore 3 e non 3.568

Questo esempio serve a capire che, attraverso le operazioni di cast si pu perdere la precisione del dato.

- 26 -

Desantis_Francesco
Costanti: allinterno di un programma pu capitare di utilizzare pi volte dei valori numerici, delle costanti quindi. Per evitare di riscrivere sempre lo stesso numero buona abitudine denire quel valore come costante. Ipotizzando di avere un programma in cui gura pi volte il , senza scrivere ogni volta il valore 3,14 consigliabile procedere con assegnazioni del tipo:
final final final final int f = 33; byte g = 125; float pg = (float) 3.14; double d = 3.1423789;

I principali vantaggi nellusare le costanti sono: - Leggibilit del programma - Modicabilit del programma: supponendo di dover cambiare per qualche motivo il valore della costante, basta modicare il valore assegnatogli nella dichiarazione senza doverlo ritoccare ogni volta che compare nel programma. OSSERVAZIONE: se la dichiarazione locale ad un metodo il campo dazione della costante il metodo stesso: se invece si tratta della dichiarazione di una variabile di istanza a cui viene applicato il modicatore nal, la costante verr associata ad ogni oggetto della classe l momento della sua creazione. Tipi di dato primitivi non numerici: oltre ai 6 tipi di dati primitivi numerici, Java offre anche 2 tipi di dati primitivi non numerici: char e boolean. Tipo di dato primitivo non numerico char: pu contenere un solo carattere tra gli oltre 64000 del suo dominio (caratteri standardizzati dallo standard Unicode). Operazioni del dato primitivo char: Assegnazione di char
char c = 'A'

Estrazione di un carattere char da un oggetto String:


String s = "Ciao"; char c = s.charAt(n);

//

mette in c il carattere di posizione n + 1 della stringa Ciao (se n = 1 allora in c andr la lettera i)

Conversione da char a String: char c = 'A';


String s = String.valueOf(c); // c diventa una stringa

Conversione da char a int

- 27 -

Appunti_Java.12.02

char c = 'A'; int i = c; //

i contiene il codice Unicode del carattere A

Conversione da int a char


int i = 65; char c = (char)i; // c contiene il carattere corrispondente al codice Unicode contenuto in i (conterr il carattere A)

Lettura di char
String s = JOptionPane.showInputDialog("Inserisci carattere"); char c = s.charAt(0); // c contiene il carattere di posizione 0+1 della stringa inserita da tastiera

Tipo di dato primitivo non numerico boolean: pu assumere solo i valori true o false e viene utilizzato per specicare delle condizioni utilizzando i principi dellalgebra di Boole. Le sue caratteristiche sono: Dimensione 1 bit Dominio vero o falso boolean && Operazioni possibili || ! and or not prodotto logico somma logica negazione logica

Letterali true e false A questo punto importante riportare anche tutti i tipi di confronto che si possono effettuare in Java ai dati di tipo numerico (oltre a gli operatori logici AND, OR e NOT presenti nella precedente tabella): == != > < >= <= uguale a (da non confondere con = utilizzato per le assegnazioni) diverso da maggiore di minore di maggiore o uguale di minore o uguale di

- 28 -

Desantis_Francesco
Applicazioni concrete dei vari dati primitivi e dei diversi confronti si avranno con lintroduzione alle istruzioni condizionali. Istruzioni condizionali: sono delle apposite istruzioni, messe a disposizione da Java (come da altri linguaggi di programmazione), che permettono di vericare una condizione ed eseguire determinate parti di codice in base al risultato della verica. In Java vi sono 2 forme di istruzione condizionale:
- if-then-else - switch

Istruzione condizionale if-then-else (se-allora-altrimenti): questa un tipo di istruzione a 2 vie. In altre parole, listruzione if si deve immaginare come un bivio formato da 2 vie: se sono vericate determinate condizioni si seguir una strada mentre, se non si vericano allora si seguir la strada opposta. Usando un linguaggio pi tecnico diremo che se sono vericate determinate condizioni verrano eseguite delle istruzioni altrimenti se ne eseguiranno delle altre. Sintassi:
if (condizione) istruzione-then else istruzione-else

// pu anche essere omessa, nel senso che non sempre c la necessit di esplicitare una condizione alternativa

Sintassi alternativa equivalente:


condizione ? istruzione-then : istruzione-else

Nel caso in cui si debba fare un confronto di uguaglianza tra stringhe, il simbolo == non consentito ma si deve utilizzare il comando a.equals("..."). Per condizione si intende un confronto tra dati. Diverse sono le possibilit si confronto: Confronto con operatori applicato a variabili di tipo primitivo
import javax.swing.JOptionPane; public } class ConfrontoOperatori { public static void main (String[] args) { int a = Integer.parseInt(JOptionPane.showInputDialog("Inserire un numero")); int b = Integer.parseInt(JOptionPane.showInputDialog("Inserire un ulteriore numero")); if (a > b ) System.out.println(a + " maggiore di " + b); else System.out.println(b + " maggiore di " + a); System.exit(0); }

Confronto applicato a variabili di tipo primitivo boolean

- 29 -

Appunti_Java.12.02

public }

class ConfrontoBoolean { public static void main (String[]args){ boolean b = true; if (b) // corrisponde a: if (b == true) System.out.println("True"); else System.out.println("False"); }

Confronto tra stringhe


import javax.swing.JOptionPane; public } class ConfrontoBoolean { public static void main (String[]args){ String a = JOptionPane.showInputDialog("Inserire si o no"); if (a.equals("si")) System.out.println("Equals si"); else System.out.println("Equals no"); }

Confronto lessicograco: per vericare se una stringa ne precede unaltra in ordine lessicograco si usa il metodo compareTo. Date 2 stringhe s e t, s.compareTo(t) restituisce: - un intero negativo, se s precede t; - 0, se s uguale a t; - un intero positivo, se s segue t; Si ricorda che una variabile che non ha associato alcun valore ha valore null. Con listruzione if-then-else si possono fare confronti anche con il null per non bisogna usare il metodo equals ma ==. Confronto composto (operatori e operazioni logiche)
import javax.swing.JOptionPane; public class ConfrontoComposto { public static void main (String[] args) { int a = Integer.parseInt(JOptionPane.showInputDialog("Inserire un numero")); int b = Integer.parseInt(JOptionPane.showInputDialog("Inserire un ulteriore numero")); if ((a + b) > 10) && ((a * b) > 100) // && loperatore logico AND

- 30 -

Desantis_Francesco
} } System.out.println("Confronto composto verifico"); else System.out.println("Confronto composto non verificato"); System.exit(0);

Come la condizione pu essere composta, anche le istruzioni then e else possono essere pi di una. Vale a dire che il programma, se viene vericata una certa condizione, pu eseguire anche pi di unistruzione; il discorso analogo se la condizione non viene verica, ad esempio: Blocco di istruzioni then e else
import javax.swing.JOptionPane; public } class BloccoIstruzioni { public static void main (String[] args) { int a = Integer.parseInt(JOptionPane.showInputDialog("Inserire un numero")); int b = Integer.parseInt(JOptionPane.showInputDialog("Inserire un ulteriore numero")); if (a > b ) { System.out.println(a + " maggiore di " + b); a -= 1; System.out.println(a); } else { System.out.println(b + " maggiore di " + a); System.exit(0); a +=1; System.out.println(a); } }

Durante la risoluzione di un problema si pu avere la necessit di inserire nellistruzione then o nellistruzione else un ulteriore istruzione condizionale. Ci consentito in Java (come in tanti altri linguaggi di programmazione) e questazione viene denita annidamento di if. If annidati
import javax.swing.JOptionPane; public class IfAnnidati { public static void Saluto(String nome) {

- 31 -

Appunti_Java.12.02
} } public } JOptionPane.showMessageDialog(null,"Ciao " + nome + " piacere di averti conosciuto");

static void main (String[] args) { String a = JOptionPane.showInputDialog("Inserisci il tuo nome"); int b = a.length(); // in b va il numero dei caratteri della stringa a if (b <= 3) { Saluto(a); JOptionPane.showMessageDialog(null,"Hai un nome cortissimo"); } else if (b <= 9) { Saluto(a); JOptionPane.showMessageDialog(null,"Hai un nome di media lunghezza"); } else if (b > 9) { Saluto(a); JOptionPane.showMessageDialog(null,"Hai un nome lunghissimo"); } System.exit(0);

In questo esempio stato fatto un abuso di annidamento poich lultima condizione si poteva anche omettere in quanto, se il nome inserito non ha lunghezza ne <= 3 e ne <= 9 allora, per forza di cose, sar > 9. Inoltre non bisogna cadere in tranelli tipo il seguente: ATTENZIONE!!!
import javax.swing.JOptionPane; public class Attenzione { public static void Saluto(String nome) { JOptionPane.showMessageDialog(null,"Ciao " + nome + " piacere di averti conosciuto"); } public static void main (String[] args) { String a = JOptionPane.showInputDialog("Inserisci il tuo nome"); int b = a.length(); if ((b <= 3) || (b == 10)) // || loperatore logico OR Saluto(a); // istruzione then System.out.println("Istruzione tra gli if!!!"); // istruzione indipendente dal then if (b > 5) System.out.println(b + " maggiore di 5"); // istruzione then System.exit(0);

- 32 -

Desantis_Francesco
} }

Istruzione switch: per realizzare una selezione a pi vie si possono usare diverse istruzioni if oppure si pu utilizzare listruzione specica switch, messa a disposizione da Java, la cui sintassi :
switch } ( espressione ) { case etichetta1 : istruzione ; break; . . . case etichetta_n : istruzione ; break; default istruzione;

Dove:
- espressione deve essere intera o di tipo char; - case etichetta rappresenta la condizione che deve essere vericata. I valori specicati devono essere espressioni costanti il cui valore deve essere noto a tempo di compilazione (non sono ammesse espressioni tipo a > 0). Questo aspetto rende listruzione switch molto limitata; - istruzione rappresenta ci che il programma deve svolgere se viene vericata listruzione o le istruzioni etichetta; - default istruzione rappresenta ci che il programma deve svolgere nel caso in cui non si verica nessuna delle condizioni case etichetta; - break pu anche essere omesso, per se ci accade verranno eseguite tutte le istruzione dei vari case presenti successivamente, no a che non si incontra un eventuale break. In generale permette di uscire prematuramente da unistruzione. Ovviamente, quando si omettono i break, diventa importante la successione in cui vengono riportati i vari case.

Esempio pratico di ci che stato detto: Istruzione switch


import javax.swing.JOptionPane; public class IstruzioneSwitch { public static void main (String[]args){ byte mese = Byte.parseByte(JOptionPane.showInputDialog("Inserisci un mese in numeri")); byte giorni = 0; String nomemese = null; switch (mese) { case 1: nomemese = "Gennaio"; giorni = 31;

- 33 -

Appunti_Java.12.02
} break; case 2: nomemese = "Febraio"; giorni = 28; break; case 3: nomemese = "Marzo"; giorni = 31; break; case 4: nomemese = "Aprile"; giorni = 30; break; case 5: nomemese = "Maggio"; giorni = 31; break; case 6: nomemese = "Giugno"; giorni = 30; break; case 7: nomemese = "Luglio"; giorni = 31; break; case 8: nomemese = "Agosto"; giorni = 31; break; case 9: nomemese = "Settembre"; giorni = 30; break; case 10: nomemese = "Ottobre"; giorni = 31; break; case 11: nomemese = "Novembre"; giorni = 30; break; case 12: nomemese = "Dicembre"; giorni = 31; break; default : JOptionPane.showMessageDialog(null, "Inserisci un mese valido"); }

if (nomemese != null) JOptionPane.showMessageDialog(null, nomemese + " ha " + giorni + " giorni"); System.exit(0); }

- 34 -

Desantis_Francesco

Ripetizioni di istruzioni: spesso pu capitare, per la risoluzione di un problema, di dover ripetere pi volte le stesse istruzioni. La maggior parte dei linguaggi di programmazione, tra cui anche Java, mettono a disposizione delle istruzioni che permettono di evitare di riscrivere lo stesso blocco di istruzioni pi volte. Queste istruzioni sono chiamate cicli iterativi. In Java, la ripetizione di istruzioni pu avvenire in 2 modi: - attraverso dei cicli iterativi, che a loro volta possono essere: - cicli deniti, ovvero cicli in cui il numero di iterazioni noto prima di iniziare lesecuzione del ciclo; - cicli indeniti, ovvero cicli il cui numero di iterazioni legato al vericarsi, durante lesecuzione del programma, di una determinata condizione durante - attraverso lutilizzo di metodi ricorsivi; In java, sia i cicli deniti che quelli indeniti, possono essere realizzati con i comandi : - while; - for; - do; Ciclo while: sintassi:

while ( condizione ) istruzione

Dove:
- condizione rappresenta lespressione di tipo boolean che pu essere vericata o meno; - istruzione rappresenta ci che il programma deve svolgere nch verica la condizione.

Un esempio pratico per assimilare le funzionalit del while pu essere il seguente: Perimetro poligono
import javax.swing.JOptionPane; public } class Perimetro { public static void main (String[]args){ byte lati = Byte.parseByte(JOptionPane.showInputDialog("Inserisci il numero dei lati del poligono")); byte n = 0; // funge da contatore per il ciclo byte perimetro = 0; // funge da accumulatore per il ciclo while (n < lati) { n++; perimetro += Byte.parseByte (JOptionPane.showInputDialog("Inserisci la lunghezza del lato")); } JOptionPane.showMessageDialog(null, "Il perimetro del poligono " + perimetro); System.exit(0); }

- 35 -

Appunti_Java.12.02
Analizziamo il seguente problema: Realizzare un software che permette linserimento di numeri da tastiera, attraverso una MessageBox, nch non si clicca su annulla. Dopodich dovr visualizzare quanti numeri sono stati inseriti, il minimo e il massimo. Ciclo while per minimo e massimo
import javax.swing.JOptionPane; public } class CicloW { public static void main (String[]args){ String s = JOptionPane.showInputDialog("Inserisci un numero"); int max = 0, min = 0, num = 0, n = 0, somma = 0; while (s != null) { n++; // incremento del contatore somma += num; // accumulatore num = Integer.parseInt(s); if (n == 1){ min = num; max = num; } else if (num < min) min = num; else if (num > max) max = num; s = JOptionPane.showInputDialog("Inserisci un numero"); } JOptionPane.showMessageDialog(null, "Hai inserito " + n + " numeri, con " + min + " numero minimo e " + max + " numero massimo" ); System.exit(0); }

Ciclo for: usato principalmente per realizzare cicli deniti. Sintassi:


for ( inizializzazione; condizione; incremento ) istruzione

Dove:
- inizializzazione di una variabile di controllo (si pu dichiarare ed inizializzare in tuttuno); - condizione rappresenta lespressione di tipo boolean che pu essere vericata o meno; - incremento della variabile di controllo; - istruzione rappresenta ci che il programma deve svolgere nch verica la condizione.

Equivale a:

- 36 -

Desantis_Francesco

inizializzazione while ( condizione ) { istruzione incremento; }

Ciascuna delle 3 parti del ciclo for (inizializzazione; condizione; incremento) pu anche mancare per non si possono omettere i 2 ; Si ripropone lesempio precedente, utilizzando il ciclo for: Ciclo for minimo e massimo
import public } javax.swing.JOptionPane; class CicloF { public static void main (String[]args){ String s = JOptionPane.showInputDialog("Inserisci un numero"); int max = 0, min = 0, n = 0, num = 0, somma = 0; for (int i = 1; s != null; i++) { somma += num; num = Integer.parseInt(s); if (n == 1){ min = num; max = num; } else if (num < min) min = num; else if (num > max) max = num; s = JOptionPane.showInputDialog("Inserisci un numero"); n = i; } JOptionPane.showMessageDialog(null, "Hai inserito " + n + " numeri, con " + min + " numero minimo e " + max + "numero massimo" ); System.exit(0); }

Ciclo do: molto simile al while, per in questo caso la condizione viene vericata alla ne. Sintassi:
do istruzione while ( condizione ) ;

Dove:

- 37 -

Appunti_Java.12.02
- condizione rappresenta lespressione di tipo boolean che pu essere vericata o meno; - istruzione rappresenta ci che il programma deve svolgere nch verica la condizione.

Si pu quindi calcolare il perimetro di un poligono anche con il do, infatti: Perimetro poligono con ciclo while
import javax.swing.JOptionPane; public } class Perimetro { public static void main (String[]args){ byte lati = Byte.parseByte(JOptionPane.showInputDialog("Inserisci il numero dei lati del poligono")); byte n = 0; byte perimetro = 0; do { n++; perimetro += Byte.parseByte (JOptionPane.showInputDialog ("Inserisci la lunghezza del lato")); } while (n < lati); JOptionPane.showMessageDialog(null, "Il perimetro del poligono " + perimetro); System.exit(0); }

Si pu osservare che il corpo del ciclo viene eseguito almeno una vota e che non , in generale, necessario inizializzare le variabili che compaiono nella condizione prima di iniziare lesecuzione del ciclo, sufficiente che tali variabili vengano inizializzate nel corpo stesso. Teorema di Jacopini-Bohm: la sequenza, listruzione if-then-else e listruzione while formano un insieme di istruzioni completo. Con gli strumenti visti no a questo momento rimane molto semplice calcolare il Massimo Comune Divisore tra due numeri. Un metodo non complicato e allo stesso tempo iterativo quello di Euclide. Esso consiste nel sostituire al numero pi grande la differenza tra i due numeri nch essi non si uguagliano. Il caso pi semplice che pu capitare quando i 2 numeri sono uguali (il M.C.D. coincide con uno dei 2 numeri). Il caso pi laborioso che pu capitare quando il M.C.D. di 2 numeri molto grandi 1. Allatto pratico avremo: Metodo di Euclide con sottrazione
import javax.swing.JOptionPane; public class Euclide { public static void main (String[]args){ JOptionPane.showMessageDialog(null, "Programma che calcola il massimo comune divisore tra 2 numeri con il metodo di Euclide"); int a = Integer.parseInt(JOptionPane.showInputDialog("Inserire primo numero"));

- 38 -

Desantis_Francesco
} } int b = Integer.parseInt(JOptionPane.showInputDialog("Inserire secondo numero")); int c = 0, d = 0; if (a == b) JOptionPane.showMessageDialog(null, "Il M.C.D. tra " + a +" e " + b + " " + a); else {c = a; d = b; while (c != d) { if (c > d) c = c - d; else d = d - c; } JOptionPane.showMessageDialog(null, "Il M.C.D. tra " + a +" e " + b + " " + c); } System.exit(0);

Fattoriale
import javax. swing.JOptionPane; public } class Fatt { public static int Fattoriale (int num) { if (num <= 0) JOptionPane.showMessageDialog(null,"Numero non valido"); else for (int i = num-1; i >= 1; i-- ) num = num*i; return num; } public } static void main (String[]args){ int n = Integer.parseInt(JOptionPane.showInputDialog("Inserisci il numero cui calcolare il suo fattoriale")); System.out.println(Fattoriale(n)); System.exit(0);

Tavola pitagorica

public class TavolaPitagorica{

- 39 -

Appunti_Java.12.02
} public } static void main (String[]args) { int ris = 0; for (int riga = 1; riga <= 10; riga++) { for (int colonna = 1; colonna <= 10; colonna++ ) { ris = riga * colonna; System.out.print(ris); if (ris < 10) // serve per un corretto incolonnamento System.out.print(" "); else System.out.print (" "); } System.out.println(); // sposta il cursore a capo per stampare le righe successive } System.exit(0);

Produce il seguente risultato:


1 2 3 4 5 6 7 8 9 10 2 4 6 8 10 12 14 16 18 20 3 6 9 12 15 18 21 24 27 30 4 8 12 16 20 24 28 32 36 40 5 10 15 20 25 30 35 40 45 50 6 12 18 24 30 36 42 48 54 60 7 14 21 28 35 42 49 56 63 70 8 16 24 32 40 48 56 64 72 80 9 18 27 36 45 54 63 72 81 90 10 20 30 40 50 60 70 80 90 100

Piramide di asterischi
import public javax.swing.JOptionPane; class Piramide{ public static void main (String[]args) { byte h = Byte.parseByte(JOptionPane.showInputDialog("Inserisci l'altezza della piramide")); for (byte r = 1; r <= h; r++) { for (byte i = 1; i <= h - r; i++) // ciclo per spazi bianchi System.out.print(" "); for (byte i = 1; i <= ((r*2)-1); i++) // ciclo per * System.out.print("*"); System.out.println(); }

- 40 -

Desantis_Francesco
} } System.exit(0);

Ipotizzando che sia stato inserito 5 come altezza della piramide si avr:
* *** ***** ******* *********

Testo criptato
import public } javax. swing.JOptionPane; class TestoCriptato{ public static void main (String[]args){ String s = JOptionPane.showInputDialog("Inserire una stringa"); int key = Integer.parseInt(JOptionPane.showInputDialog("Inserire chiave di criptaggio")); String ss = ""; for (int i = 0; i < s.length(); i++) { char c = s.charAt(i); int code = c + key; char cc = (char)code; ss = ss + cc; } JOptionPane.showMessageDialog(null,ss); System.exit(0); }

Inserita in in-put una stringa qualsiasi ed un intero come chiave di criptaggio, il programma comunica a schermo la stessa stringa con i caratteri incrementati dellintero inserito. Ad esempio, inserendo ciao e 3 come chiave si avr: fldr. Verica di un numero primo
import public javax.swing.JOptionPane; class NumPrimo{ public static void main (String[]args) { int a = Integer.parseInt(JOptionPane.showInputDialog("Inserisci un numero")); boolean b = false;

- 41 -

Appunti_Java.12.02
} } for (int i = 2; i < (a-1); i++){ if ((a % i) == 0) b = true; } if (b == true) JOptionPane.showMessageDialog(null, a + " NON un numero primo"); else JOptionPane.showMessageDialog(null, a + " un numero primo"); System.exit(0);

Listruzione break (vedere p.36) pu essere usata anche allinterno di in ciclo, per esempio: Calcolo delle radici quadrate (istruzione break)
import javax.swing.JOptionPane; public } class Radice{ public static void main (String[]args) { double a; for (int i = 0; i < 10; i++) { a = Double.parseDouble(JOptionPane.showInputDialog("Immetti un reale non negativo")); if (a >= 0) System.out.println(Math.sqrt(a)); else { System.out.println("Errore"); break; // dopo aver stampato 'Errore' finisce di ciclare } } System.exit(0); }

Un metodo equivalente per il precedente esempio pu essere: Calcolo delle radici quadrate (metodo equivalente)
import javax.swing.JOptionPane; public class Radice{ public static void main (String[]args) {

- 42 -

Desantis_Francesco
} } double a; boolean errore = false; for (int i = 0; (i < 10) && !errore; i++) { a = Double.parseDouble(JOptionPane.showInputDialog("Immetti un reale non negativo")); if (a >= 0) System.out.println(Math.sqrt(a)); else { System.out.println("Errore"); errore = true; // dopo aver stampato 'Errore' finisce di ciclare } } System.exit(0);

Istruzione continue
import public } javax.swing.JOptionPane; class Dispari{ public static void main (String[]args) { int n = 10; for (int i = 0; i < n; i++) { if (i%2 == 0) // se il resto della divisione i/2 = 0 allora continue; // NON esegue le istruzioni successive e passa all'iterazione dopo else System.out.println(i); } }

In pratica questo programma stampa tutti i numeri dispari compresi tra 1 e 10. Concetto di... Array: un oggetto Array contiene una collezione di elementi dello stesso tipo, ognuno dei quali caratterizzato dalla propria posizione. In altre parole un Array pu essere immaginato come un insieme di variabili disposte una consecutivamente allaltra come a formare una cassettiera con una colonna e n cassetti. Per usare un Array, oltre a dichiarare il tipo e ad inserire i dati allinterno di esso, si deve anche specicare la dimensione, ovvero il numero dei cassetti; infatti la sua sintassi :
TipoArray [] NomeArray = new TipoArray [Dimensione];

Se lArray di tipo int allora viene automaticamente inizializzato con il valore 0, altrimenti, se di tipo String viene inizializzato con il valorore null. Creazione di un oggetto Array:

- 43 -

Appunti_Java.12.02

int [] a = new int [10];

In questo modo si crea un oggetto di tipo Array di tipo int, con dimensione 10 ed inizializzato con il valore 0 Inserire elementi in un oggetto Array:

int [] a = { 6, 9, 27, 4, 10 }; // equivale a int [] a = new int [5]; a[0] = 6; a[1] = 9; a[2] = 27; a[3] = 4; a[4] = 10;

// i numeri dentro le quadre stanno ad identificare la posizione in cui sar inserito lelemento numerico (posizione 0 contiene il numero 6)

Questi sono 2 metodi equivalenti per creare un Array di dimensione 5 ed inizializzarli con i valori 6, 9, 27, 4, 10. Inserimento ciclico e stampa elementi di un Array
import public } javax.swing.JOptionPane; class StampaArray{ public static void main (String[]args) { int[] a = new int [10]; for (int i = 0; i < a.length ; i++) // ciclo per inserimento ciclico a[i] = Integer.parseInt(JOptionPane.showInputDialog("Inserisci un numero")); for (int i = 0; i < a.length; i++) // ciclo per stampare elementi dellArray System.out.println(a[i]); System.exit(0); }

Inserimento ciclico e stampa somma elementi di un Array


import public javax.swing.JOptionPane; class SommaArray{ public static void main (String[]args) { int[] a = new int [10]; int somma = 0; for (int i = 0; i < a.length ; i++) // ciclo per inserimento ciclico a[i] = Integer.parseInt(JOptionPane.showInputDialog("Inserisci un numero")); for (int i = 0; i < a.length; i++) // ciclo per stampare la somma degli elementi dell'Array somma += a[i]; JOptionPane.showMessageDialog(null, "La somma degli elementi inseriti : " + somma); System.exit(0); }

- 44 -

Desantis_Francesco
}

Inserimento ciclico e ricerca sequenziale di un elemento in un Array


import public } javax.swing.JOptionPane; class Ricerca{ public static void main (String[]args) { int[] a = new int [10]; int somma = 0; for (int i = 0; i < a.length ; i++) // ciclo per inserimento ciclico a[i] = Integer.parseInt(JOptionPane.showInputDialog("Inserisci un numero")); int num = Integer.parseInt(JOptionPane.showInputDialog("Inserisci un numero da cercare")); boolean trovato = false; for (int i = 0; i < a.length; i++) // ciclo per ricerca sequenziale if (num == a[i]) trovato = true; // SUGGERIMENTO: si pu inserire anche il comando break if (trovato == true) JOptionPane.showMessageDialog(null, num + " tra i numeri inseriti"); else JOptionPane.showMessageDialog(null, "Spiacente!!! " + num + " NON tra i numeri inseriti"); System.exit(0); }

In questo modo, dopo aver inserito 10 interi allinterno dellArray, il programma li confronta tutti con il numero da ricercare e comunica se presente allinterno dellArray. Se viene inserito il comando break (dove suggerito), si possono far risparmiare diverse elaborazioni al compilatore in quanto smette il ciclo della ricerca non appena trova il numero da cercare inserito. Ovviamente se il numero da cercare non presente o si trova nellultima posizione dellArray allora il numero di cicli sar equivalente per ognuno dei 2 metodi di ricerca. Inserimento ciclico e ricerca sequenziale dellelemento pi grande in un Array
import public javax.swing.JOptionPane; class Maggiore { public static void main (String[]args) { int[] a = new int [10]; int nmax = 0; for (int i = 0; i < a.length; i++) a[i] = Integer.parseInt(JOptionPane.showInputDialog("Inserisci un numero")); for (int i = 0; i < a.length; i++) { if (i == 0) nmax = a[i]; else if (nmax < a[i])

- 45 -

Appunti_Java.12.02
} } nmax = a[i]; } JOptionPane.showMessageDialog(null,"Il numero pi grande inserito " + nmax); System.exit(0);

Concetto di... Matrice: una matrice un insieme di pi Array. Pu anche esser denita come un Array bidimensionale, cio un Array con n righe ed m colonne. In altre parole, una matrice pu esser benissimo paragonata ad una comune cassettiera. Anche per le matrici, come per gli Array, oltre a dichiarare il tipo e ad inserire i dati allinterno di essa, si deve anche specicare la dimensione, ovvero il numero dei cassetti e il numero delle colonne di cassetti; infatti la sua sintassi :
TipoMatrice [] [] NomeMatrice = new TipoMatrice [NumeroRighe] [NumeroColonne];

Ovviamente anche per le matrici, se sono di tipo int allora verranno automaticamente inizializzate con il valore 0, altrimenti, se sono di tipo String verranno inizializzate con il valorore null. Creazione di una matrice:
int [] [] a = new int [10] [10];

In questo modo si crea una matrice di int, con 10 righe, 10 colonne ed inizializzata con il valore 0. Inserire elementi in una matrice:

int [] [] a = { { 3, 5, 9 } { 7, 13, 21 } } // equivale a int [] [] a = new int [2] [3]; a [0][0] = 3; a [0][1] = 5; a [0][3] = 9; a [1][0] = 7; a [1][1] = 13; a [1][3] = 21;

Stampa del numero di righe e di colonne di una matrice


import public javax.swing.JOptionPane; class RigheColonne { public static void main (String[]args) { int a[][] = new int [10][15]; JOptionPane.showMessageDialog(null, "La matrice ha " + a.length + " righe e " + a[0].length + " colonne");

- 46 -

Desantis_Francesco
} } System.exit(0);

Inserimento ciclico degli elementi di una matrice e visualizzazione della matrice inserita
import public } javax.swing.JOptionPane; class InserimentoStampaMatrice { public static void main (String[]args) { int r = Integer.parseInt(JOptionPane.showInputDialog("Inserisci il numero di righe della matrice")); int c = Integer.parseInt(JOptionPane.showInputDialog("Inserisci il numero di colonne della matrice")); int n; int a[][] = new int [r][c]; for (int rr = 0; rr < r; rr++ ) // ciclo per scandire le righe for (int cc = 0; cc < c; cc++) { // ciclo per avanzare di colonna n = Integer.parseInt(JOptionPane.showInputDialog("Inserisci valore di posto: riga = " + (rr + 1) + " ; colonna = " + (cc + 1))); a[rr][cc] = n; // inserimento del valore di input allinterno della matrice } JOptionPane.showMessageDialog(null, "OK! Matrice correttamente inserita"); for (int rr = 0; rr < r; rr++ ) { // 1 - ciclo per scandire le righe for (int cc = 0; cc < c; cc++) // 2 - ciclo per avanzare di colonna System.out.print(a[rr][cc]+ " "); // 3 - stampa della matrice System.out.println(); } System.exit(0); }

Volendo si pu stampare a schermo anche la matrice trasposta. Questo ottenibile attraverso 2 modi distinti ma equivalenti: - scambiare il ciclo 1 - ciclo per scandire le righe con il ciclo 2 - ciclo per avanzare di colonna; - scambiare [rr] con [cc] (e viceversa) nella riga di codice 3 - stampa della matrice. Inserimento ciclico di elementi in una matrice e somma delle righe in un Array
import javax.swing.JOptionPane; public class SommaRigheInArray { public static int[][] InsMat (int[][]m) { int n;

- 47 -

Appunti_Java.12.02
} } public } for (int r = 0; r < m.length; r++ ) for (int c = 0; c < m[0].length; c++) { n = Integer.parseInt(JOptionPane.showInputDialog("Inserisci numero di posto: riga = " + (r+ 1) + " ; colonna = " + (c + 1))); m[r][c]=n; } JOptionPane.showMessageDialog(null, "OK! Matrice correttamente inserita"); return m;

static int[] SommaRighe(int m[][]){ int a[] = new int[m.length]; for (int r = 0; r < m.length; r++) { for (int c = 0; c < m[0].length; c++) { a[r] += m[r][c]; } } return a;

public static void StampaArray (int a[]) { for (int i = 0; i < a.length; i++) System.out.println(a[i]); } public } static void main (String[]args) { int r = Integer.parseInt(JOptionPane.showInputDialog("Inserisci il numero di righe della matrice")); int c = Integer.parseInt(JOptionPane.showInputDialog("Inserisci il numero di colonne della matrice")); int a[][] = new int [r][c]; InsMat(a); StampaArray(SommaRighe(a)); System.exit(0);

Inserimento ciclico degli elementi di due matrici e prodotto delle due


import javax.swing.JOptionPane; public class ProdottoMat { public static void InsMat (int [][] mat) {

- 48 -

Desantis_Francesco
} public } public } for (int i = 0; i < mat.length; i++) for (int j = 0; j < mat[0].length; j++) mat[i][j] = Integer.parseInt(JOptionPane.showInputDialog("Inserisci l'elemento posto in " + (i+1) + "^ riga e " + (j+1) + "^ colonna"));

static void StampaMat (int [][]mat){ for (int i = 0; i < mat.length; i++){ for (int j = 0; j < mat[0].length; j++) System.out.print(" " + mat[i][j]); System.out.println(); }

static int[][] Prodotto (int[][]m1, int[][]m2, int[][]m3){ for (int r = 0; r < m3.length; r++ ) for (int c = 0; c < m3 [0].length; c++){ m3[r][c]=0; for (int i = 0; i < m3.length; i++) m3[r][c] += m1[r][i]*m2[i][c]; } JOptionPane.showMessageDialog(null, "Prodotto tra matrici effettuato"); return m3;

public

static void main (String [] args){ int r = Integer.parseInt(JOptionPane.showInputDialog("Inserisci il numero di righe della prima matrice")); int c = Integer.parseInt(JOptionPane.showInputDialog("Inserisci il numero di colonne della prima matrice")); int rr = Integer.parseInt(JOptionPane.showInputDialog("Inserisci il numero di righe della seconda matrice")); int cc = Integer.parseInt(JOptionPane.showInputDialog("Inserisci il numero di colonne della seconda matrice")); int m [][] = new int [r][c]; int mm [][] = new int [rr][cc]; int mp [][] = new int [r][cc]; if (c != rr) JOptionPane.showMessageDialog(null, "ERRORE! Il numero di colonne della prima marice deve essere uguale al numero di righe della seconda matrice"); else { JOptionPane.showMessageDialog(null, "Inseimento degli elementi della prima matrice"); InsMat(m); JOptionPane.showMessageDialog(null, "Inseimento degli elementi della seconda matrice");

- 49 -

Appunti_Java.12.02
} } InsMat(mm); System.out.println("Prima matrice inserita:"); StampaMat(m); System.out.println("Seconda matrice inserita:"); StampaMat(mm); System.out.println("Prodotto tra le 2 matrici"); StampaMat(Prodotto(m, mm, mp)); } System.exit(0);

Concetto di... File: i piccoli programmi svolti nora utilizzano memoria R.A.M., cio ogni singolo dato contenuto in una variabile o su un Array viene praticamente perso nel momento in cui termina il programma. I le rappresentano la principale struttura per la memorizzazione di dati in maniera permanente su memoria di massa. Questo vuol dire che i dati contenuti in un le potranno essere accessibili in qualsiasi momento. Ogni le caratterizzato da un nome e da una directory (indirizzo in cui salvato allinterno di un calcolatore). Le operazioni fondamentali che si possono fare sui sono la creazione, scrittura, lettura, rinominazione ed eliminazione. Per eseguire operazioni di lettura e scrittura sui le necessario aprire il le prima di eseguire le operazioni e chiudere il le al termine dellesecuzione delle operazioni. - Aprire un le signica indicare al sistema operativo la volont di eseguire operazioni sui le. Lapertura del le pu essere: - Apertura in scrittura: unapplicazione va ad alterare il contenuto del le; - Apertura in lettura: diverse applicazioni possono leggere lo stesso le senza per modicarne il contenuto. In molti linguaggi di programmazione, uno fra tutti Java, lapertura in scrittura di un le coincide con la sua creazione. - Chiudere un le signica suggerire al sistema operativo che il le precedentemente aperto non pi usato dal programma (assicura la scrittura su disco). Concetto di... Eccezioni: le operazioni sui le possono provocare situazioni inattese che il programma non sa gestire, dette eccezioni. Esse sono classicate in base al tipo di inconveniente che si vericato e devono essere gestite dal programmatore. Ad esempio, i metodi per lapertura di un le in scrittura/lettura possono generare uneccezione di tipo IOException. Tutti i metodi in cui vi sono operazioni sui le devono dichiarare esplicitamente questa eccezione preceduti dalla clausola throws. Sintassi intestazione metodi: public/private static/NonStatico TipoRisultato NomeMetodo (parametri) throws IOException Scrittura su le
import public java.io.*; class ScritturaFile { public static void main (String[]args) throws IOException { // intestazione metodo main con eccezioni di tipo In-put/Out-put FileWriter f = new FileWriter("Prova.text"); // apertura file per scrittura PrintWriter out = new PrintWriter(f); // creazione dell'oggetto per la scrittura out.println("testo di prova"); // scrittura del testo su file out.close(); // chiusura file (oggetto di classe PrintWriter) f.close(); // chiusura file (oggetto di classe FileWriter) }

- 50 -

Desantis_Francesco
}

Crea un le di testo chiamato Prova.text con la stessa directory del file.java e contenente testo di prova. Se in quella directory esiste gi un le con quel nome viene automaticamente sostituito con il nuovo. Per aggiungere del testo ad un le.text gi esistente bisogna effettuare un apertura file per scrittura utilizzando listruzione FileWriter f = new FileWriter("Prova.text", true);

Ciclo di scrittura su le di un Array di stringhe


import public } java.io.*; class CicloScritturaFile { public static void SalvaArray (String[] v, String nomefile) throws IOException { // intestazione metodo con eccezioni di tipo In-put/Out-put FileWriter f = new FileWriter(nomefile); // apertura file per scrittura PrintWriter out = new PrintWriter(f); // creazione dell'oggetto per la scrittura for (int i = 0; i < v.length; i++) // ciclo che scrive su file per tutta la lunghezza dellArray out.println(v[i]); // scrive su file lelemento dellArray di posizione i out.close(); // chiusura file (oggetto di classe PrintWriter) f.close(); // chiusura file (oggetto di classe FileWriter) }

Lettura da le
import public } java.io.*; class LetturaFile { public static void main (String[]args) throws IOException { // intestazione metodo con eccezioni di tipo In-put/Out-put FileReader f = new FileReader("prova.text"); // apertura del file per la lettura BufferedReader in = new BufferedReader(f); // creazione di un buffer che conterr tutto ci che presente nel file String linea = in.readLine(); // lettura dal buffer di una linea (restituisce null se avviene End-Of-File (EOF)) System.out.println(linea); // stampa della linea su video f.close(); // chiusura file (oggetto di classe FileReader) }

OSSERVAZIONE: il comando BufferedReader serve per copiare in un buffer il contenuto di un le opportunamente aperto in lettura. Una volta effettuata questa copia si potranno utilizzare i dati di un le non andando direttamente ad attingere sul le ma utilizzando il buffer creato e riempito. In altre parole il buffer svolge la funzione di tramite tra il le e il programma che necessita di utilizzare il contenuto del le.

- 51 -

Appunti_Java.12.02
Ciclo lettura da le
import public } java.io.*; class CicloLetturaFile { public static String[] CaricaArray (String NomeFile) throws IOException { // intestazione metodo con eccezioni di tipo In-put/Out-put FileReader fr = new FileReader(NomeFile); // apertura del file per la lettura BufferedReader in = new BufferedReader(fr); // creazione di un buffer che conterr tutto ci che presente nel file int n = 0; // inizializzazione della variabile da incrementare per stabilire la dimensione dellArray String linea = in.readLine(); // legge la prima riga dal buffer e restituisce null se avviene End-Of-File (EOF) while (linea != null) { // condizione EOF n++; // (per ogni riga non nulla n = n + 1)ogni riga letta sul buffer corrisponde ad una casella dellArray linea = in.readLine(); // legge dal buffer la prossima linea del buffer (restituisce null se avviene End-Of-File (EOF)) } fr.close(); // chiusura file (oggetto di classe FileReader) } String[] v = new String[n]; // creazione dell'Array di dimensione n dove n rappresenta il numero di righe del file fr = new FileReader(NomeFile); // si riapre il file per la lettura in = new BufferedReader(fr); // creazione di un nuovo buffer che conterr tutto ci che presente nel file String linea2 = in.readLine(); // legge la prima riga del buffer e restituisce null se avviene End-Of-File (EOF) for (int i = 0; (linea2 != null) && (i < n); i++){ // condizione EOF && indice Array < lunghezza Array v[i] = linea2; // inserisce nella posizione i dellArray il contenuto di una linea del buffer linea2 = in.readLine(); // legge dal buffer la prossima riga del buffer (restituisce null se avviene End-Of-File (EOF)) } fr.close(); // chiusura file (oggetto di classe FileReader) return v; // ritorna con un Array contenente le stesse righe del file

Il metodo restituisce un Array di stringhe corrispondenti alle linee di un le. Si noti che vengono effettuati due cicli: - primo ciclo: conta il numero di linee del le in modo da dimensionare correttamente lArray; - secondo ciclo: riempie lArray dichiarato e dimensionato. OSSERVAZIONE: il comando readLine() ha la capacit di leggere una sola riga di un buffer. E da osservare che allinterno di un ciclo non bisogna manualmente indicare con una variabile contatore la linea di testo che si andr a leggere (un po come avviene per accede al contenuto di una casella di un Array) perch lincremento, con il comando in questione, automatico, ovvero legge automaticamente la linea successiva. Cancellazione di le
File f1 = new File("Prova.text"); // creazione delloggetto f1 di tipo file con il nome del file da eliminare passato come parametro f1.delete(); // metodo con risultato di tipo boolean: restituisce true se la cancellazione ha esito positivo

- 52 -

Desantis_Francesco

Rinominazione di le
File f1 = new File("VecchioNome.text"); // creazione delloggetto f1 di tipo file con il nome del file da rinominare passato come parametro File f2 = new File("Nuovonome.text"); // creazione delloggetto f2 di tipo file con il nuovo nome del file da rinominare passato come parametro f1.renameTo(f2) // metodo con risultato di tipo boolean: restituisce true se la rinominazione ha esito positivo

Inserimento ciclico di una matrice, salvataggio su le della matrice e della sua trasposta, lettura e stampa a schermo il contenuto del le
import javax.swing.JOptionPane; import java.io.*; public class Completo { public } public } public } static int[][] InsMat (int [][] mat) { for (int i = 0; i < mat.length; i++ ) for (int j = 0; j < mat[0].length; j++) mat[i][j] = Integer.parseInt(JOptionPane.showInputDialog("Inserisci il valore posto nella " + (i+1) + "^ riga e " + (j+1) + "^ colonna")); return mat;

static void SaveMat (int [][] mat, PrintWriter out) throws IOException { out.println("Matrice inserita"); for (int i = 0; i < mat.length; i++){ for (int j = 0; j < mat[0].length; j++) out.print((mat[i][j]) + " "); out.println(""); }

static void SaveMatTras (int [][] mat, PrintWriter out) throws IOException { out.println(""); out.println("Matrice trasposta"); for (int i = 0; i < mat.length; i++){ for (int j = 0; j < mat[0].length; j++) out.print((mat[j][i]) + " "); out.println(""); }

public static String[] CaricaArray (String NomeFile) throws IOException {

- 53 -

Appunti_Java.12.02

FileReader fr = new FileReader(NomeFile); BufferedReader in = new BufferedReader(fr); int n = 0; String linea = in.readLine(); while (linea != null) { n++; linea = in.readLine(); } fr.close(); String[] v = new String[n]; fr = new FileReader(NomeFile); in = new BufferedReader(fr); String linea2 = in.readLine(); for (int i = 0; (linea2 != null) && (i < n); i++){ v[i] = linea2; linea2 = in.readLine(); } fr.close(); return v;

public static void StampaArray (String [] a){ for (int i = 0; i < a.length; i++) System.out.println(a[i]); } public static void main (String[]args) throws IOException { int r = Integer.parseInt(JOptionPane.showInputDialog("Inserire il numero di righe della matrice")); int c = Integer.parseInt(JOptionPane.showInputDialog("Inserire il numero di colonne della matrice")); int m [][] = new int [r][c]; InsMat(m); FileWriter fw = new FileWriter ("PrimaMatrice.text"); PrintWriter pw = new PrintWriter (fw); SaveMat(m,pw); SaveMatTras(m,pw); pw.close(); fw.close(); JOptionPane.showMessageDialog(null,"Inserimento e salvataggio avvenuto con successo");

- 54 -

Desantis_Francesco
}

System.out.println("Il file contiene:"); StampaArray(CaricaArray("PrimaMatrice.text"));

Concetto di... Ricorsione: un metodo si dice ricorsivo se al suo interno contiene unattivazione di s stesso (eventualmente indirettamente attraverso lattivazione di altri metodi). La tecnica della programmazione ricorsiva consiste nellesplicitare una o pi condizioni base per le quali il risultato pu essere determinato direttamente per poi esprimere delle condizioni ricorsive che alla ne muteranno in una delle condizioni base iniziali. Questa tecnica (anche se abbastanza ostica) pu essere utilizzata come alternativa ai classici cicli iterativi trattati in precedenza. Metodi ricorsivi elementari
import javax.swing.JOptionPane; public class RicorsioneElementare { public } public } public static int somma (int x, int y){ // metodo ricorsivo per effettuare la somma tra 2 numeri if (y == 0) // condizione base1 return x; if (x == 0) // condizione base2 return y; else return 1 + somma(x,y-1); // condizione ricorsiva (ogni volta che si "cicla" il numero 1 si incrementa finch y = 0)

static int prodotto (int x, int y) { // metodo ricorsivo per effettuare il prodotto tra 2 numeri if ((y == 0)||( x== 0)) // condizione base1 return 0; if (x == 1) // condizione base2 return y; if (y == 1) // condizione base3 return x; else return somma(x,prodotto(x,y-1)); // condizione ricorsiva (il prodotto viene visto come un insieme di somme)

static int fattoriale (int x) { // metodo ricorsivo per effettuare il prodotto fattoriale di un numero if (( x== 0)||(x == 1)) // condizione base return 1; else return x * fattoriale(x-1); // condizione ricorsiva (si moltiplica un numero per i suoi numeri precedenti finch x = 1)

- 55 -

Appunti_Java.12.02
} } public } public } static int potenza (int b, int e){ // metodo ricorsivo per effettuare una potenza if (e == 0) // condizione base return 1; else return prodotto(b,potenza(b,e-1)); // condizione ricorsiva (la potenza viene vista come un insieme di moltiplicazioni)

static void main( String args[] ) { // metodo cliente main int xx = Integer.parseInt(JOptionPane.showInputDialog("Inserisci un numero")); int yy = Integer.parseInt(JOptionPane.showInputDialog("Inserisci un altro numero")); System.out.println("La somma tra " + xx + " e " + yy + " : " + somma(xx,yy)); System.out.println("Il prodotto tra " + xx + " e " + yy + " : " + prodotto(xx,yy)); System.out.println(xx + "! = " + fattoriale(xx)); System.out.println(yy + "! = " + fattoriale(yy)); System.out.println(xx + "^" + yy + " = " + potenza(xx,yy)); System.out.println(yy + "^" + xx + " = " + potenza(yy,xx)); System.exit(0);

Metodi simili, ovviamente, si possono applicare anche a stringhe. Un metodo ricorsivo per ottenere il numero di volte cui si ripete un carattere allinterno di una stringa pu essere il seguente:
public } static int ContaLettere (String s, char c) { // metodo ricorsivo che restituisce il numero di volte cui ripetuto un carattere in una stringa if (s.length() == 0) return 0; else if (s.charAt(0) == c) return 1 + ContaLettere(s.substring(1),c); else return ContaLettere(s.substring(1),c);

Riguardo alla ricorsione vi sono tante altre applicazioni, unaltra tra cui quella della dei le, ovvero si pu interagire con i le di dati senza usare cicli iterativi. Alcuni metodi possono essere:
public static int Massimo (BufferedReader br) throws IOException { // metodo ricorsivo che restituisce il numero pi grande di una colonna salvata su file String s = br.readLine(); if (s == null) return 0;

- 56 -

Desantis_Francesco
} public } public } public } public else { int i = Integer.parseInt(s); int m = Massimo(br); return (m > i) ? m : i; }

static int ContaRighe (BufferedReader br) throws IOException { String s = br.readLine(); if (s == null) return 0; else return 1 + ContaRighe(br);

// metodo ricorsivo che restituisce il numero di righe di un file

static int ContaRigheIniziali (BufferedReader br) throws IOException { String s = br.readLine(); if (s == null) return 0; else if (s.charAt(0) == 'a') return 1 + ContaRigheIniziali(br); else return ContaRigheIniziali(br);

// metodo ricorsivo che restituisce il numero di righe di un file dove il primo carattere la lettera a

static int SommaVettoreFile (BufferedReader br) throws IOException { // metodo ricorsivo che restituisce la somma dei numeri di una colonna salvata su file String s = br.readLine(); if (s == null) return 0; else return Integer.parseInt(s) + SommaVettoreFile (br);

static boolean Presente (int val, BufferedReader br) throws IOException{ String s = br.readLine(); if (s == null) return false; else { if (Integer.parseInt(s) == val) return true; else return Presente(val, br);

// metodo ricorsivo che restituisce true se il numero da cercare presente altrimenti false

- 57 -

Appunti_Java.12.02
} }

- 58 -