Il tipo di dati “stringa”spazioinwind.libero.it/inginfotv/appunti/fondinfo1/pdf/...Fondamenti di...
Transcript of Il tipo di dati “stringa”spazioinwind.libero.it/inginfotv/appunti/fondinfo1/pdf/...Fondamenti di...
Fondamenti di Informatica 1 Settimana 2
Marcello Dalpasso 1
1
Stringhe
2
Il tipo di dati “stringa”✔ I tipi di dati più importanti nella maggior parte dei
programmi sono i numeri e le stringhe✔ Una stringa è una sequenza di caratteri, che in
Java (come in molti altri linguaggi) vannoracchiusi tra virgolette– le virgolette non fanno parte della stringa
✔ Possiamo dichiarare e inizializzare variabili ditipo stringa
✔ Possiamo assegnare un valore ad una variabile ditipo stringa
String name = "John";
"Hello"
name = "Michael";
3
Il tipo di dati “stringa”✔ Diversamente dai numeri, le stringhe sono oggetti
– infatti, il tipo di dati String inizia con la maiuscola!– invece, int e double iniziano con la minuscola…
✔ Una variabile di tipo stringa può quindi essereutilizzata per invocare metodi della classe String– ad esempio, il metodo length restituisce la lunghezza di
una stringa, cioè il numero di caratteri presenti in essa(senza contare le virgolette)String name = "John";int n = name.length(); 4
4
Il tipo di dati “stringa”✔ Il metodo length della classe String non è un
metodo statico– infatti per invocarlo usiamo un oggetto della classe
String, e non il nome della classe stessa
✔ Una stringa di lunghezza zero, che non contiene caratteri,si chiama stringa vuota e si indica con due caratterivirgolette consecutivi, senza spazi interposti
// NON FUNZIONA!String s = "John";int n = String.length(s);
// FUNZIONAString s = "John";int n = s.length();
String empty = "";System.out.println(empty.length()); 0
5
Estrazione di sottostringhe✔ Per estrarre una sottostringa da una stringa si usa il
metodo substring
– il primo parametro di substring è la posizione delprimo carattere che si vuole estrarre
– il secondo parametro è la posizione successivaall’ultimo carattere che si vuole estrarre
String greeting = "Hello, World!";String sub = greeting.substring(0, 4);// sub contiene "Hell"
H e oll , W o dlr !0 1 432 5 7 8 11109 126
Attenzione allaminuscola!
6
Estrazione di sottostringhe✔ La posizione dei caratteri nelle stringhe viene
stranamente numerata a partire da 0 anziché da 1– in linguaggi precedenti, come il C e il C++, questa era
un’esigenza tecnica, mentre in Java non lo è più e si èmantenuta questa strana caratteristica soltanto peruniformità con tali linguaggi molto diffusi
✔ Alcune cose da ricordare– la posizione dell’ultimo carattere corrisponde alla
lunghezza della stringa meno 1– la differenza tra i due parametri di substring
corrisponde alla lunghezza della sottostringa estratta
Fondamenti di Informatica 1 Settimana 2
Marcello Dalpasso 2
7
Estrazione di sottostringhe✔ Il metodo substring può essere anche invocato
con un solo parametro
✔ In questo caso il parametro fornito indica laposizione del primo carattere che si vuole estrarre,e l’estrazione continua fino al termine della stringa
String greeting = "Hello, World!";String sub = greeting.substring(7);// sub contiene "World!"
H e oll , W o dlr !0 1 432 5 7 8 11109 126
8
Estrazione di sottostringhe✔ Cosa succede se si fornisce un parametro
errato a substring?
✔ Il programma viene compilato correttamente,ma viene generato un errore in esecuzione
// NON FUNZIONA!String greeting = "Hello, World!";String sub = greeting.substring(0, 14);
Exception in thread “main”java.lang.StringIndexOutOfBoundsExceptionString index out of range: 14
9
Concatenazione di stringhe✔ Per concatenare due stringhe si usa l’operatore +
✔ L’operatore di concatenazione è identicoall’operatore di addizione– se una delle espressioni a sinistra o a destra
dell’operatore + è una stringa, l’altra espressione vieneconvertita in stringa e si effettua la concatenazione
String s1 = "li";String s2 = "re";String s3 = s1 + s2; // s3 contiene lireint lit = 15000;String s = lit + s3; // s contiene "15000lire"
10
Concatenazione di stringhe
✔ Osserviamo che la concatenazione prodotta non èproprio quella che avremmo voluto, perché mancauno spazio tra 15000 e lire– l’operatore di concatenazione non aggiunge spazi! (meno male, diremo la maggior parte delle volte…)
✔ L’effetto voluto si ottiene così
int lit = 15000;String litName = "lire";String s = lit + litName;// s contiene "15000lire"
String s = lit + " " + litName;Non è una stringa
vuota, ma una stringacon un solo carattere,
uno spazio (blank)
11
Concatenazione di stringhe✔ La concatenazione è molto utile per ridurre il
numero di enunciati usati per stampare i risultatidei programmi
✔ Bisogna fare attenzione a come viene gestito ilconcetto di “andare a capo” (cioè alla differenzatra print e println)
int total = 10;System.out.print("Il totale è ");System.out.println(total);
int total = 10;System.out.println("Il totale è " + total);
12
Classi e oggetti
Fondamenti di Informatica 1 Settimana 2
Marcello Dalpasso 3
13
Motivazioni✔ Elaborando numeri e stringhe si possono scrivere
programmi interessanti, ma programmi più utilihanno bisogno di manipolare dati più complessi– conti bancari, dati anagrafici, forme grafiche…
✔ Il linguaggio Java gestisce questi dati complessisotto forma di oggetti
✔ Gli oggetti ed il loro comportamento vengonodescritti mediante le classi ed i loro metodi
14
Oggetti✔ Un oggetto è un’entità che può essere manipolata
in un programma mediante l’invocazione di metodi– System.out è un oggetto che si può manipolare (usare)
mediante il suo metodo println✔ Per il momento, consideriamo che un oggetto sia
una “scatola nera” (black box) dotata di– un’interfaccia pubblica (i metodi che si possono usare),
che definisce il comportamento dell’oggetto– una realizzazione (implementazione) nascosta (il codice dei metodi ed i loro dati)
15
Classi✔Una classe
– è una fabbrica di oggetti• gli oggetti che si creano sono esemplari (“istanze”,
instance) di una classe, che ne è il prototipo– specifica i metodi che si possono invocare per
gli oggetti che sono esemplari di tale classe(l’interfaccia pubblica)
– definisce i particolari della realizzazione deimetodi (codice e dati)
– è un contenitore di• metodi statici (Hello contiene main)• oggetti statici (System contiene out)
Finora abbiamo vistosolo questo aspetto,
che è forse quellomeno importante
16
Usare una classe✔ Iniziamo lo studio delle classi analizzando come si
usano oggetti di una classe che si suppone giàdefinita da altri– vedremo quindi che è possibile usare oggetti di cui non
si conoscono i dettagli realizzativi, un concetto moltoimportante della programmazione orientata agli oggetti,come abbiamo già visto con oggetti di tipo String
✔ In seguito, analizzeremo i dettagli realizzatividella classe che abbiamo imparato ad utilizzare– usare oggetti di una classe– realizzare una classe
Sono due attivitàben distinte!
17
Usare la classe BankAccount✔ Abbiamo a disposizione una classe che descrive il
comportamento di un conto bancario✔ Tale comportamento consente di
– depositare denaro nel conto– prelevare denaro dal conto– chiedere il valore del saldo del conto
✔ Le operazioni consentite dal comportamento di unoggetto si effettuano mediante l’invocazione dimetodi
account.deposit(1000);
account.withdraw(500);
System.out.println("Saldo: " + account.getBalance());
18
Usare la classe BankAccount✔Trasferiamo denaro da un conto ad un altro
✔Calcoliamo e accreditiamo gli interessi diun conto
double amount = 500;account1.withdraw(amount);account2.deposit(amount);
double rate = 0.05; // interessi del 5%double amount = account.getBalance() * rate;account.deposit(amount);
Fondamenti di Informatica 1 Settimana 2
Marcello Dalpasso 4
19
Costruire oggetti✔ Sappiamo quindi come operare su un conto
bancario, ma non sappiamo come “aprire unnuovo conto bancario”, cioè creare un nuovooggetto di tipo BankAccount
✔ Se vogliamo creare un oggetto ed usarlo più volteabbiamo bisogno di memorizzarlo da qualcheparte nel programma
✔ Per conservare un oggetto si usa una variabileoggetto, che conserva non l’oggetto stesso, mainformazioni sulla sua posizione nella memoriadel computer si dice che è un riferimento o puntatore
20
Le variabili oggetto✔ Per definire una variabile oggetto si indica il nome
della classe ai cui oggetti farà riferimento lavariabile, seguito dal nome della variabile stessa
✔ In Java, ciascuna variabile oggetto è di un tipo specifico epotrà fare riferimento soltanto ad oggetti di quel tipo
✔ La definizione di una variabile oggetto crea un riferimentonon inizializzato, cioè la variabile non fa riferimento adalcun oggetto
BankAccount account;
BankAccount account;
account ?
21
Costruire oggetti BankAccount✔ Per creare un nuovo oggetto di una classe si usa
l’operatore new seguito dal nome della classe e dauna coppia di parentesi tonde
✔ L’operatore new crea un nuovo oggetto e nerestituisce un riferimento, che può essere assegnatoad una variabile oggetto del tipo appropriato
new BankAccount();
BankAccount account = new BankAccount();
account BankAccount
22
Costruire oggetti BankAccount✔ Che caratteristiche ha l’oggetto appena creato?
– qual è il saldo del nuovo conto bancario?✔ Le proprietà di un oggetto appena creato dipendono da
come è realizzata la classe, quindi la descrizione di taliproprietà deve far parte delle informazioni forniteall’utilizzatore della classe, la documentazione della classe
✔ Nel caso della classe BankAccount, un oggettoappena creato ha un saldo di valore zero, senzadubbio una scelta di progetto molto ragionevole
23
La classe BankAccount✔ Senza sapere come sia stata realizzata la classe
BankAccount, siamo in grado di aprire un nuovoconto bancario e di depositarvi un po’ di denarodouble initialDeposit = 1000;BankAccount account = new BankAccount();System.out.println("Saldo: " + account.getBalance());account.deposit(initialDeposit);System.out.println("Saldo: " + account.getBalance());
Saldo: 0Saldo: 1000
24
Intervallo
���������������������
������������
Fondamenti di Informatica 1 Settimana 2
Marcello Dalpasso 5
25
Definire i metodi
26
Il progetto di BankAccount✔ Sapendo già il comportamento della classe BankAccount,
il suo progetto consiste nella definizione della classe✔ Per definire una classe occorre realizzarne i metodi
– deposit– withdraw– getBalance
public class BankAccount{ public void deposit(double amount) { realizzazione del metodo } public void withdraw(double amount) { realizzazione del metodo } public double getBalance() { realizzazione del metodo }
dati della classe}
27
✔ La definizione di un metodo inizia sempre con lasua intestazione (firma, signature), composta da– uno specificatore di accesso
• in questo caso public, altre volte vedremo private
– il tipo di dati restituito dal metodo (double, void...)– il nome del metodo (deposit, withdraw, getBalance)– un elenco di parametri, eventualmente vuoto,
racchiuso tra parentesi tonde• di ogni parametro si indica il tipo ed il nome• più parametri sono separati da una virgola
public void deposit(double amount)public double getBalance()
Le intestazioni dei metodi
28
Lo specificatore di accesso✔ Lo specificatore di accesso di un metodo indica
quali altri metodi possono invocare il metodo✔ Dichiarando un metodo public si consente
l’accesso a qualsiasi altro metodo di qualsiasialtra classe
– è comodo per programmi semplici e faremosempre così, salvo casi eccezionali
29
Il tipo di dati restituito✔ La dichiarazione di un metodo specifica quale sia
il tipo di dati restituito dal metodo al termine dellasua invocazione– ad esempio, getBalance restituisce un valore di tipo
double✔ Se un metodo non restituisce alcun valore, si
dichiara che restituisce il tipo speciale void(assente, non valido…)
double b = account.getBalance();
double b = account.deposit(500); // ERROREaccount.deposit(500); // OK
30
Variabili di esemplare
Fondamenti di Informatica 1 Settimana 2
Marcello Dalpasso 6
31
Lo stato di un oggetto✔ Gli oggetti (quasi tutti…) hanno bisogno di
memorizzare il proprio stato attuale, cioèl’insieme dei valori che descrivono l’oggetto e cheinfluenzano (anche se non necessariamente) ilrisultato dell’invocazione dei metodi dell’oggetto
✔ Gli oggetti della classe BankAccount hannobisogno di memorizzare il valore del saldo delconto bancario che rappresentano
✔ Lo stato di un oggetto viene memorizzatomediante variabili di esemplare (o “variabili diistanza”, instance variables)
32
Variabili di esemplare
✔ La dichiarazione di una variabile di esemplare ècostituita da– uno specificatore di accesso
• in questo caso private, altre volte vedremo public– il tipo di dati della variabile (double)– il nome della variabile (balance)
public class BankAccount{ ... private double balance; ...}
33
Variabili di esemplare✔ Ciascun oggetto (“esemplare”) della classe ha una
propria copia delle variabili di esemplare
tra le quali non esiste nessuna relazione: possonoessere modificate indipendentemente l’unadall’altra
account11000balance
BankAccount
account22000balance
BankAccount
34
Dichiarazione di variabili di esemplare
✔ Sintassi:
✔ Scopo: definire una variabile nomeVariabile ditipo TipoVariabile, una cui copia sia presente inogni oggetto della classe NomeClasse
public class NomeClasse{ ... tipoDiAccesso TipoVariabile nomeVariabile; ...}
35
Variabili di esemplare✔ Così come i metodi sono di solito “pubblici”
(public), le variabili di esemplare sono di solito“private” (private)
✔ Le variabili di esemplare private possono esserelette o modificate soltanto da metodi della classea cui appartengono– le variabili di esemplare private sono nascoste (hidden)
al programmatore che utilizza la classe, e possonoessere lette o modificate soltanto mediantel’invocazione di metodi pubblici della classe
– questa caratteristica dei linguaggi di programmazioneorientati agli oggetti si chiama incapsulamento oinformation hiding
36
Incapsulamento✔ Poiché la variabile balance di BankAccount è
private, non vi si può accedere da metodi che nonsiano della classe (errore semantico segnalato dalcompilatore)
✔ Si possono usare solo i metodi pubblici!
/* codice interno ad un metodo che non appartiene a BankAccount */double b = account.balance; // ERRORE
balance has private access in BankAccount
double b = account.getBalance(); // OK
Fondamenti di Informatica 1 Settimana 2
Marcello Dalpasso 7
37
Incapsulamento✔ L’incapsulamento ha molti vantaggi, soltanto
pochi dei quali potranno essere evidenziati inquesto corso di base
✔ Il vantaggio fondamentale è quello di impedirel’accesso incontrollato allo stato di un oggetto,impedendo così anche che l’oggetto venga(accidentalmente o deliberatamente) posto in unostato inconsistente
✔ Il progettista della classe BankAccount potrebbedefinire (ragionevolmente) che soltanto un saldonon negativo rappresenti uno stato consistente perun conto bancario
38
Incapsulamento✔ Dato che il valore di balance può essere
modificato soltanto invocando i metodi deposit owithdraw, il progettista può impedire che diventinegativo, magari segnalando una condizioned’errore (ma ancora non sappiamo come farlo…)
✔ Se invece fosse possibile assegnare direttamenteun valore a balance dall’esterno, ogni sforzo delprogettista di BankAccount sarebbe vano
✔ Si noti che, per lo stesso motivo e anche perrealismo, non esiste un metodo setBalance, datoche il saldo di un conto bancario non può essereimpostato ad un valore qualsiasi!
39
Realizzare i metodi
40
I metodi di BankAccount✔ La realizzazione dei metodi di BankAccount è
molto semplice– lo stato dell’oggetto (il saldo del conto) è memorizzato
nella variabile di esemplare balance– quando si deposita o si preleva una somma di denaro, il
saldo del conto si incrementa o si decrementa dellastessa somma
– il metodo getBalance restituisce il valore del saldocorrente memorizzato nella variabile balance
✔ Questa realizzazione non impedisce che un contoassuma saldo negativo perché non sappiamo fare!– vedremo in seguito come realizzare un controllo
41
I metodi di BankAccountpublic class BankAccount{ public void deposit(double amount) { balance = balance + amount; } public void withdraw(double amount) { balance = balance - amount; } public double getBalance() { return balance; }
private double balance;}
42
L’enunciato return✔ Sintassi:
✔ Scopo: terminare l’esecuzione di un metodo,ritornando all’esecuzione sospesa del metodoinvocante. Se è presente una espressione, questadefinisce il valore restituito dal metodo e deveessere del tipo dichiarato nella firma del metodo
return espressione;
return;
Fondamenti di Informatica 1 Settimana 2
Marcello Dalpasso 8
43
I parametri dei metodipublic void deposit(double amount){ balance = balance + amount;}
✔ Cosa succede quando invochiamo il metodo?
✔ L’esecuzione del metodo dipende da due valori– il riferimento all’oggetto account– il valore 500
✔ Quando viene eseguito il metodo, il suoparametro esplicito amount assume il valore 500– esplicito perché compare nella firma del metodo
account.deposit(500);
44
✔ Nel metodo vengono utilizzate due variabili– amount è il parametro esplicito del metodo– balance si riferisce alla variabile di esemplare balance
della classe BankAccount, ma sappiamo che di talevariabile esiste una copia per ogni oggetto
✔ Alla variabile balance di quale oggetto si riferisceil metodo?– si riferisce alla variabile che appartiene all’oggetto con
cui viene invocato il metodo, ma come fa?
I parametri dei metodipublic void deposit(double amount){ balance = balance + amount;}
45
✔ All’interno di ciascun metodo, il riferimento all’oggettocon il quale è eseguito il metodo si chiama parametroimplicito e si indica con la parola chiave this– in questo caso, this assume il valore di account
all’interno del metodo deposit✔ Ogni metodo ha sempre uno ed un solo parametro
implicito, dello stesso tipo della classe a cui appartiene ilmetodo– eccezione: i metodi statici non hanno parametro implicito
✔ Il parametro implicito non deve essere dichiarato e sichiama sempre this
Il parametro implicito dei metodi
account.deposit(500);
46
✔ La vera sintassi del metodo dovrebbe essere
ma nessun programmatore Java scriverebbe così,perché Java consente una comoda scorciatoia– quando in un metodo ci si riferisce ad una variabile di
esemplare, il compilatore costruisce automaticamenteun riferimento alla variabile di esemplare dell’oggettorappresentato dal parametro implicito this
Uso del parametro implicito
public void deposit(double amount){ this.balance = this.balance + amount;}// this è di tipo BankAccount
47
Il riferimento null
48
Il riferimento null✔ Una variabile di un tipo numerico fondamentale
contiene sempre un valore valido (eventualmentecasuale, se non è stata inizializzata in alcun modo)
✔ Una variabile oggetto può invece contenere unriferimento a nessun oggetto valido assegnandoalla variabile il valore null, che è una parolachiave del linguaggio
– vedremo in seguito applicazioni utili di questa proprietà
BankAccount account = null;
Fondamenti di Informatica 1 Settimana 2
Marcello Dalpasso 9
49
Il riferimento null✔ Diversamente dai valori numerici, che in Java non
sono oggetti, le stringhe sono oggetti– una variabile oggetto di tipo String può contenere un
riferimento nullString greeting = "Hello";String emptyString = ""; // stringa vuotaString nullString = null; // riferimento nullint x1 = greeting.length(); // vale 5int x2 = emptyString.length(); // vale 0// nel caso seguente l’esecuzione del programma// termina con un erroreint x3 = nullString.length(); // errore
50
Usare un riferimento null✔ Una variabile oggetto che contiene un riferimento
null non si riferisce ad alcun oggetto
– non può essere usata per invocare metodi✔ Se viene usata per invocare metodi, l’interprete
termina l’esecuzione del programma, segnalandoun errore di tipo NullPointerException (pointer èun sinonimo di reference, “riferimento”)
51
L’ENIAC e gli albori dell’informatica
✔ L’ENIAC (Electronic Numerical Integrator AndComputer) fu il primo computer elettronico,realizzato all’università di Pennsylvania nel 1946
✔ Occupava una grande stanza ed era costituito damolti armadi con circa 18000 valvole (analoghe aitransistori), parecchie delle quali si bruciavanoogni giorno e dovevano essere sostituite
✔ Veniva programmato collegando cavi su appositipannelli, simili a quelli dei centralini telefonici, edandava nuovamente programmato in tal modo perogni specifico problema
52
L’ENIAC e gli albori dell’informatica
✔ Il progetto fu finanziato dalla Marina statunitenseper il calcolo di tavole balistiche da usare per lastima della traiettoria di un proiettile in funzionedella resistenza del vento, della velocità iniziale edelle condizioni atmosferiche
✔ Questo problema richiedeva la soluzione numericadi equazioni differenziali (numerical integrator)
✔ Questi calcoli venivano precedentemente svolti daesseri umani, detti computer, letteralmente“calcolatori” (manuali...)
✔ Più tardi l’ENIAC venne usato per catalogare idati del servizio demografico statunitense
53
���������������������
��������������������������������
54
Elaborazioni con stringhe
Fondamenti di Informatica 1 Settimana 2
Marcello Dalpasso 10
55
Alcuni metodi utili di String✔ Un problema che capita spesso di affrontare è
quello della conversione di una stringa perottenerne un’altra tutta in maiuscolo o tutta inminuscolo
✔ La classe String mette a disposizione due metodi– toUpperCase converte tutto in maiuscolo– toLowerCase converte tutto in minuscoloString s = "Hello";String ss = s.toUpperCase() + s.toLowerCase();// ss vale "HELLOhello"
56
Alcuni metodi utili di String
✔ Si noti che l’applicazione di uno di questi metodialla stringa s non altera il contenuto della stringas, ma restituisce una nuova stringa
✔ In particolare, nessun metodo della classe Stringmodifica l’oggetto con cui viene invocato!– si dice perciò che gli oggetti della classe String
sono oggetti immutabili
String s = "Hello";String ss = s.toUpperCase() + s.toLowerCase();// s vale ancora "Hello" !
57
Esempio✔ Scriviamo un programma che genera la password
per un utente, con la regola seguente– si prendono le iniziali dell’utente, le si rendono
minuscole e si concatena l’età dell’utenteespressa numericamente
(in realtà questa regola non è assolutamente dausare, perché è prevedibile e quindi poco sicura!)
Utente: Marcello DalpassoEtà: 35⇒⇒⇒⇒ Password: md35
58
Esempiopublic class MakePassword{ public static void main(String[] args) { String firstName = "Marcello"; String lastName = "Dalpasso"; int age = 35; // estrai le iniziali String initials = firstName.substring(0, 1) + lastName.substring(0, 1); // converti in minuscolo e concatena l’età String pw = initials.toLowerCase() + age; // stampa la password System.out.println("La password è " + pw); }}
59
Conversione di stringhe in numeri✔ A volte si ha una stringa che contiene un valore
numerico e si vuole assegnare tale valore ad unavariabile di tipo numerico, per poi elaborarlo
✔ Il compilatore segnala l’errore semantico perchénon si può convertire automaticamente una stringain un numero, dato che non vi è certezza che ilsuo contenuto rappresenti un valore numerico
String password = "md35";String ageString = password.substring(2);// ageString contiene "35"// NON FUNZIONA!int age = ageString;
incompatible typesfound : java.lang.Stringrequired: int
60
Conversione di stringhe in numeri✔ La conversione corretta si ottiene invocando il
metodo statico parseInt della classe Integer
✔ La conversione di un numero in virgola mobile siottiene, analogamente, invocando il metodo staticoparseDouble della classe Double
int age = Integer.parseInt(ageString);// age contiene il numero 35
String numberString = "34.3";double number = Double.parseDouble(numberString);// number contiene il numero 34.3
Fondamenti di Informatica 1 Settimana 2
Marcello Dalpasso 11
61
✔ Per convertire un numero in stringa si puòconcatenare il numero con la stringa vuota
✔ È però più elegante utilizzare il metodo toStringdelle classi Integer e Double, rispettivamente pernumeri interi e numeri in virgola mobile
Conversione di numeri in stringhe
int ageNumber = 10;String ageString = "" + ageNumber;// ageString contiene "10"
int ageNumber = 10;String ageString = Integer.toString(ageNumber);
62
✔ A volte la conversione automatica di numeri instringhe, eseguita con la concatenazione o con imetodi toString, non fornisce il risultato voluto
✔ Ad esempio, quando si elaborano valori monetari
Problemi nelle conversioni
double euro = 23127.32;final double TAX_RATE = 17.5;System.out.println("Reddito: " + euro + " euro");double tax = euro * TAX_RATE / 100;System.out.println("Tassa: " + tax + " euro");
Reddito: 23127.32 euroTassa: 4047.281 euro
I millesimi di euro nonesistono, sarebbe meglioscrivere 4047.28
63
✔ Per effettuare conversioni di numeri in stringhe inmodo controllato (cioè non automatico), si puòusare la classe java.text.NumberFormat
Conversioni sotto controllo
double euro = 23127.32;final double TAX_RATE = 17.5;System.out.println("Reddito: " + euro + " euro");double tax = euro * TAX_RATE / 100;NumberFormat formatter = NumberFormat.getNumberInstance();formatter.setMaximumFractionDigits(2);formatter.setMinimumFractionDigits(2);String taxStr = formatter.format(tax);System.out.println("Tassa: " + taxStr + " euro");
64
✔ Per prima cosa otteniamo un oggetto NumberFormatinvocando un metodo statico
✔ Poi impostiamo il numero massimo di cifre decimali
e anche il numero minimo
(altrimenti 4.30 viene stampato come 4.3)✔ Infine, effettuiamo la conversione invocando il metodo
format dell’oggetto formatter
Conversioni sotto controllo
NumberFormat formatter = NumberFormat.getNumberInstance();
formatter.setMaximumFractionDigits(2);
formatter.setMinimumFractionDigits(2);
String taxStr = formatter.format(tax);
65
✔ Nel caso specifico dei valori monetari, una validaalternativa è l’utilizzo di un particolare oggetto di tipoNumberFormat che contiene già le impostazioni corretteper convertire i valori monetari in una stringa– tale oggetto si ottiene invocando un metodo statico
✔ La stringa che viene stampata rispetta il formatomonetario della divisa (currency) locale
Conversione di valori monetari
NumberFormat currency = NumberFormat.getCurrencyInstance();
System.out.println(currency.format(1025.3));
L. 1.025In Italia viene stampato un numero intero, con il puntocome separatore delle migliaia e con il prefisso L.
66
Leggere l’input con laclasse ConsoleReader
Fondamenti di Informatica 1 Settimana 2
Marcello Dalpasso 12
67
I dati in ingresso ai programmi✔ I programmi visti finora non sono molto utili,
visto che eseguono sempre la stessa elaborazionead ogni esecuzione
✔ Il programma MakePassword genera sempre lapassword md35– se si vuole che generi la password per un altro utente (o
per lo stesso utente invecchiato…), è necessariomodificare il codice sorgente (in particolare, leinizializzazioni delle variabili) e compilarlo di nuovo
✔ I programmi utili hanno bisogno di ricevere datiin ingresso dall’utente
68
L’input standard dei programmi✔ Il modo più semplice e immediato per fornire dati
in ingresso ad un programma consiste nell’utilizzodella tastiera– altri metodi fanno uso del mouse, del microfono…
✔ Abbiamo visto che tutti i programmi Java hannoaccesso al proprio output standard, tramitel’oggetto System.out di tipo PrintStream
✔ Analogamente, l’interprete Java mette adisposizione dei programmi in esecuzione ilproprio input standard (flusso di input), tramitel’oggetto System.in di tipo InputStream
69
La classe ConsoleReader✔ Sfortunatamente, la classe InputStream non
possiede metodi comodi per la ricezione di datinumerici e stringhe– PrintStream ha invece il comodissimo metodo print
✔ Per ovviare a questo inconveniente, useremo laclasse ConsoleReader, che non fa parte dellalibreria standard– questa classe verrà analizzata in maggiore dettaglio in
seguito, per ora impareremo soltanto ad utilizzarla✔ Lo scopo della classe ConsoleReader è quello di
fornire una comoda interfaccia all’oggettoSystem.in
70
Il metodo readLine di ConsoleReader✔ Prima di tutto bisogna creare un nuovo oggetto
della classe ConsoleReader,poi si può invocare ilsuo metodo, senza parametri
✔ Durante l’esecuzione del metodo readLine diConsoleReader, il programma si ferma edattende l’introduzione dell’input da tastiera, chetermina quando l’utente batte il tasto Invio
✔ Il metodo readLine restituisce un oggetto di tipoString che contiene tutto quanto battutodall’utente sulla tastiera, tranne il carattere Invio(carattere di “fine riga” o “andata a capo”)
ConsoleReader console = new ConsoleReader();String line = console.readLine();
71
La classe ConsoleReader✔ Dato che la classe ConsoleReader non fa parte
della libreria standard, per utilizzarla nei propriprogrammi è necessario copiare il file sorgenteConsoleReader.java (o il solo file compilatoConsoleReader.class) all’interno della cartellain cui si trovano i propri file sorgenti
✔ È consigliabile utilizzare questa classe per i primiprogrammi Java, per poi passare ad utilizzare imetodi standard per la lettura dei dati dall’inputstandard
72
Esempiopublic class MakePassword2{ public static void main(String[] args) { ConsoleReader c = new ConsoleReader(); System.out.println("Inserire il nome"); String firstName = c.readLine(); System.out.println("Inserire il cognome"); String lastName = c.readLine(); System.out.println("Inserire l’età"); int age = Integer.parseInt(c.readLine()); String initials = firstName.substring(0, 1) + lastName.substring(0, 1); String pw = initials.toLowerCase() + age; System.out.println("La password è " + pw); }}
Fondamenti di Informatica 1 Settimana 2
Marcello Dalpasso 13
73
Intervallo
���������������������
�������
������������
74
Ancora sui dati numerici
75
Intervalli numerici e precisione✔ Come molte rappresentazioni di dati in un
computer, anche la rappresentazione di numeri inJava soffre di alcune limitazioni, dovute a scelteprogettuali di compromesso tra la precisione dellarappresentazione e la velocità di elaborazionedelle operazioni aritmetiche in Java
✔ I valori di tipo int sono compresi tra -2147483648 (costante Integer.MIN_VALUE) +2147483647 (costante Integer.MAX_VALUE)
quindi, ad esempio, la popolazione mondiale nonpuò essere rappresentata con una variabile int
76
Intervalli numerici e precisione✔ I numeri in virgola mobile hanno invece un
intervallo di variabilità molto più ampio– i double, ad esempio, hanno un valore assoluto
massimo di circa 10308 (Double.MAX_VALUE) ma soffrono di un altro importante problema, la
mancanza di precisione, perché possonorappresentare “soltanto” 15 cifre significative
✔ Cosa significa “mancanza di precisione”?– significa che a volte le operazioni aritmetiche con
numeri in virgola mobile danno risultati inattesi...
77
public class Discount{ public static void main(String[] args) { // prezzo cento milioni di miliardi // (100.000.000.000.000.000) di lire double price = 1E17; // applichiamo uno sconto di 50 lire ! double discountedPrice = price - 50; // ora calcoliamo lo sconto effettivo // e ci aspettiamo che sia di 50 lire... double discount = price - discountedPrice; // ma lo sconto e’ di sole 48 lire !!! System.out.println(discount); }}
Intervalli numerici e precisione
78
Altri tipi di dati numerici✔ Quando il tipo int non rappresenta in modo
soddisfacente le esigenze numeriche del problema,si possono usare altri tipi di dati interi in Java
✔ Se l’intervallo di variabilità è insufficiente, si puòusare il tipo long– il massimo valore assoluto esprimibile con una
variabile di tipo long è circa 9 miliardi di miliardi(Long.MAX_VALUE e Long.MIN_VALUE)
– per assegnare un valore numerico ad una variabile ditipo long bisogna aggiungere un carattere L alla fine
long x = 3000000000L;
Fondamenti di Informatica 1 Settimana 2
Marcello Dalpasso 14
79
Altri tipi di dati numerici✔ Esistono altri due tipi di dati per numeri interi
– byte, con valori tra -128 e +127– short, con valori tra -32768 e +32767
✔ Come già accennato, esiste anche un altro tipo didati per numeri in virgola mobile, float, le cuivariabili occupano meno spazio in memoria e (avolte...) vengono elaborate più velocemente, mahanno una precisione molto limitata (7 cifresignificative)
✔ Questi tipi di dati si usano molto raramente, maalcuni metodi di classi della libreria standardrichiedono l’uso di parametri di tipo byte o float
80
Altri tipi di dati numerici✔ Come possiamo elaborare numeri interi o numeri
in virgola mobile che non rientrino nel campo divariabilità di long o double? Come possiamoelaborare numeri in virgola mobile con precisionearbitraria (cioè con tutta la precisione necessariaper il problema in esame)?
✔ Il pacchetto java.math della libreria standardmette a disposizione due classi per rappresentarerispettivamente numeri interi (BigInteger) enumeri in virgola mobile (BigDecimal) checonsentono di fare ciò, anche se in modo piuttostolento e scomodo...
81
Altri tipi di dati numericiimport java.math.BigInteger;
public class BigNumbers{ public static void main(String[] args) { BigInteger a = new BigInteger("123456789"); BigInteger b = new BigInteger("987654321"); BigInteger c = a.multiply(b); System.out.println(c); }}
121932631112635269
82
I pacchetti di classi (package)✔ Tutte le classi della libreria standard sono raccolte
in pacchetti (package) e sono organizzate perargomento e/o per finalità– la classe BigInteger appartiene al pacchetto java.math
✔ Per usare una classe di una libreria, bisognaimportarla nel programma, usando l’enunciato– import nomePacchetto.NomeClasse
✔ Le classi System e String appartengono alpacchetto java.lang– il pacchetto java.lang viene importato automaticamente
83
Importare una classe da un pacchetto
✔ Sintassi:✔ Scopo: importare una classe da un pacchetto, per
poterla utilizzare in un programma✔ Sintassi:✔ Scopo: importare tutte le classi di un pacchetto,
per poterle utilizzare in un programma✔ Nota: le classi del pacchetto java.lang non hanno
bisogno di essere importate✔ Attenzione: non si possono importare più
pacchetti con un solo enunciato
import nomePacchetto.NomeClasse;
import nomePacchetto.*;
import java.*.*; // ERRORE
84
Stili per l’importazione di classi✔ Usare un enunciato import per ogni classe importata
✔ Usare un enunciato import che importa tutte le classi diun pacchetto– non è un errore importare classi che non si usano!– se si usano più enunciati di questo tipo, non è più chiaro
il pacchetto di appartenenza di ciascuna classe
– sapere a quale pacchetto appartiene una classe è utile, ad esempio,per reperire la documentazione della sua interfaccia pubblica
import java.math.BigInteger;import java.math.BigDecimal;
import java.math.*;
import java.io.*;import java.math.*;
Se adesso usiamo la classe File, aquale pacchetto appartiene?
Fondamenti di Informatica 1 Settimana 2
Marcello Dalpasso 15
85
Stili per l’mportazione di classi
✔ Non usare per nulla gli enunciati import, edindicare sempre il nome completo delle classiutilizzate nel codice
✔ Questo stile è assai poco usato, perché è moltonoioso, aumenta la probabilità di errori di battiturae aumenta la lunghezza delle linee del codice(diminuendo così la leggibilità del programma)
java.math.BigInteger a = new java.math.BigInteger("123456789");
86
��������������������������������
��������������������������
87
Costruttori
88
I costruttori✔ La classe BankAccount è stata realizzata quasi
completamente, manca il codice per creare unnuovo conto bancario, con saldo a zero
✔ Per consentire la creazione di un nuovo oggetto diuna classe, inizializzandone lo stato, dobbiamoscrivere un costruttore per la classe
public class BankAccount{ public BankAccount() { balance = 0; } ...}
✔ I costruttori hannosempre lo stessonome della classe
89
public BankAccount(){ balance = 0;}I costruttori
✔ Lo scopo principale di un costruttore è quello diinizializzare le variabili di esemplare
✔ I costruttori, come i metodi, sono solitamentepubblici, per consentire a chiunque di creareoggetti della classe
✔ La sintassi utilizzata per definire i costruttori èmolto simile a quella dei metodi, ma– il nome dei costruttori è sempre uguale a quello della
classe– i costruttori non restituiscono alcunché e non bisogna
neppure dichiarare che restituiscono void
90
Invocazione di costruttori✔ I costruttori si invocano soltanto con l’operatore
new✔ L’operatore new riserva la memoria per l’oggetto,
mentre il costruttore definisce il suo stato iniziale✔ Il valore restituito dall’operatore new è il
riferimento all’oggetto appena creato einizializzato– quasi sempre il valore dell’operatore new viene
memorizzato in una variabile oggettoBankAccount account = new BankAccount();// ora account ha saldo zero
new BankAccount();
Fondamenti di Informatica 1 Settimana 2
Marcello Dalpasso 16
91
Definizione di costruttori✔ Sintassi:
✔ Scopo: definire il comportamento di un costruttoredella classe NomeClasse
✔ Nota: i costruttori servono ad inizializzare levariabili di esemplare di oggetti appena creati
public class NomeClasse{ ... tipoDiAccesso NomeClasse (TipoParametro nomeParametro,...) { realizzazione del costruttore } ...}
92
Il costruttore predefinito✔ Cosa succede se non definiamo un costruttore per
una classe?– il compilatore genera un costruttore predefinito (senza alcuna segnalazione d’errore)
✔ Il costruttore predefinito di una classe– è pubblico e non richiede parametri– inizializza tutte le variabili di esemplare
• a zero le variabili di tipo numerico• al valore speciale null le variabili oggetto, in modo
che tali variabili non si riferiscano ad alcun oggetto
93
Una classe con più costruttori✔ Una classe può avere più di un costruttore✔ Ad esempio, definiamo un costruttore per creare
un nuovo conto bancario con un saldo inizialediverso da zeropublic class BankAccount{ public BankAccount(double initialBalance) { balance = initialBalance; } public BankAccount() { balance = 0; } ...}
94
Una classe con più costruttori✔ Per usare il nuovo costruttore di BankAccount,
bisogna fornire il parametro initialBalance
✔ Notiamo che, se esistono più costruttori in unaclasse, hanno tutti lo stesso nome, perché devonocomunque avere lo stesso nome della classe– questo fenomeno (più metodi o costruttori con lo
stesso nome) è detto sovraccarico del nome(overloading)
– il compilatore decide quale costruttore invocarebasandosi sul numero e sul tipo dei parametri fornitinell’invocazione
BankAccount account = new BankAccount(500);
95
Una classe con più costruttori✔ Il compilatore effettua la risoluzione
dell’ambiguità nell’invocazione di costruttori ometodi sovraccarichi
✔ Se non trova un costruttore che corrisponda aiparametri forniti nell’invocazione, segnala unerrore semantico// NON FUNZIONA!BankAccount a = new BankAccount("tanto");
cannot resolve symbolsymbol : constructor BankAccount (java.lang.String)location : class BankAccount
96
Sovraccarico del nome✔ Se si usa lo stesso nome per metodi diversi, il
nome diventa sovraccarico (nel senso di carico disignificati diversi…)– questo accade spesso con i costruttori, dato che se una classe ha
più di un costruttore, essi devono avere lo stesso nome
– accade più di rado con i metodi, ma c’è un motivo benpreciso per farlo (ed è bene farlo in questi casi)
• usare lo stesso nome per metodi diversi (cherichiedono parametri di tipo diverso) sta ad indicareche viene compiuta la stessa elaborazione su tipi didati diversi
Fondamenti di Informatica 1 Settimana 2
Marcello Dalpasso 17
97
Sovraccarico del nome✔ La libreria standard di Java contiene numerosi
esempi di metodi sovraccarichi
✔ Quando si invoca un metodo sovraccarico, ilcompilatore risolve l’invocazione individuandoquale sia il metodo richiesto sulla base deiparametri espliciti che vengono forniti
public class PrintStream{ public void println(int n) {...} public void println(double d) {...} ...}
98
La classe BankAccountpublic class BankAccount{ public BankAccount() { balance = 0; } public BankAccount(double initialBalance) { balance = initialBalance; } public void deposit(double amount) { balance = balance + amount; } public void withdraw(double amount) { balance = balance - amount; } public double getBalance() { return balance; } private double balance;}
99
✔ In questo caso il compilatore non è in grado dicompilare la classe Program, perché non sa aquale oggetto applicare il metodo deposit, che nonè un metodo statico e quindi richiede sempre unriferimento ad un oggetto da usare comeparametro implicito
public class Program{ public static void main(String[] args) { BankAccount account = new BankAccount(); deposit(500); // ERRORE }}
Invocare un metodo senza oggetto
100
Invocare un metodo senza oggetto✔ Ci sono, però, casi in cui è ammesso (ed è pratica
molto comune!) invocare metodi non statici senzaspecificare un riferimento ad oggetto
✔ Questo accade quando si invoca un metodo nonstatico di una classe da un altro metodo nonstatico della stessa classe– viene usato il parametro implicito thispublic void withdraw(double amount){ balance = getBalance() - amount;}
this.getBalance()
101
Tentare di ricostruire un oggetto✔ A volte viene la tentazione di invocare un
costruttore su un oggetto già costruito conl’obiettivo di riportarlo alle condizioni inizialiBankAccount account = new BankAccount();account.deposit(500);account.BankAccount(); // NON FUNZIONA!
cannot resolve symbolsymbol : method BankAccount ( )location : class BankAccount
✔ Il messaggio d’erroreè un po’ strano… ilcompilatore cerca
un metodo BankAccount, non un costruttore, enaturalmente non lo trova!
102
Tentare di ricostruire un oggetto✔ Un costruttore crea un nuovo oggetto con
prefissate condizioni iniziali– un costruttore può essere invocato soltanto con
l’operatore new✔ La soluzione è semplice
– assegnare un nuovo oggetto alla variabile oggetto checontiene l’oggetto che si vuole “ricostruire”
BankAccount account = new BankAccount();account.deposit(500);account = new BankAccount();
Fondamenti di Informatica 1 Settimana 2
Marcello Dalpasso 18
103
Esempio: utilizzo di BankAccount✔ Scriviamo un programma che usi la classe
BankAccount per risolvere un problema specifico– viene aperto un conto bancario, con un saldo
iniziale di 10000 euro– ogni anno viene automaticamente accreditato
nel conto un importo (interesse annuo) pari al 5per cento del valore del saldo, senza fareprelievi né depositi
– qual è il saldo del conto dopo due anni?
104
Esempio: utilizzo di BankAccountpublic class BankAccountTest{ public static void main(String[] args) { BankAccount acct = new BankAccount(10000); final double RATE = 5; // calcola gli interessi dopo il primo anno double interest = acct.getBalance() * RATE / 100; // somma gli interessi dopo il primo anno acct.deposit(interest); System.out.println("Saldo dopo un anno: " + acct.getBalance() + " euro"); // calcola gli interessi dopo il secondo anno interest = acct.getBalance() * RATE / 100; // somma gli interessi dopo il secondo anno acct.deposit(interest); System.out.println("Saldo dopo due anni: " + acct.getBalance() + " euro"); }}
105
Un programma con più classi✔ Nota: per scrivere semplici programmi con più
classi, si possono usare due strategie (equivalenti)– scrivere ciascuna classe in un file diverso, ciascuno
avente il nome della classe con estensione .java– scrivere tutte le classi in un unico file
• un file .java può contenere una sola classe public• la classe che contiene il metodo main deve essere public• le altre classi non devono essere public (non serve scrivere
private, semplicemente non si indica l’attributo public)• il file deve avere il nome della classe public, sempre con
estensione .java
106
Intervallo
���������������
������������������
107
Copiare i riferimenti agli oggetti
108
Copiare variabili✔ Il comportamento della copia di variabili è molto diverso
nel caso in cui si tratti di variabili oggetto o di variabili ditipi numerici fondamentalidouble x1 = 1000:double x2 = x1;x2 = x2 + 500;System.out.println(x1);System.out.println(x2);
10001500
BankAccount account1 = new BankAccount(1000);BankAccount account2 = account1;account2.deposit(500);System.out.println(account1.getBalance());System.out.println(account2.getBalance());
15001500
Fondamenti di Informatica 1 Settimana 2
Marcello Dalpasso 19
109
Copiare variabili✔ Le variabili di tipi numerici fondamentali
indirizzano una posizione in memoria che contieneun valore, che viene copiato con l’assegnazione– cambiando il valore di una variabile, non viene
cambiato il valore dell’altra✔ Le variabili oggetto indirizzano una posizione in
memoria che, invece, contiene un riferimento adun oggetto, e solo tale riferimento viene copiatocon l’assegnazione– modificando lo stato dell’oggetto, tale modifica è
visibile da entrambi i riferimenti– non viene creata una copia dell’oggetto!
110
Copiare variabili
1000balanceaccount1
account2BankAccount
x1
x21000
1000
Si modificaquesto valore
111
Copiare variabili✔ Se si vuole ottenere anche con variabili oggetto lo stesso
effetto dell’assegnazione di variabili di tipi numericifondamentali, è necessario creare esplicitamente unacopia dell’oggetto con lo stesso stato, inizializzarloadeguatamente e assegnarlo alla seconda variabile oggettoBankAccount account1 = new BankAccount(1000);BankAccount account2 = new BankAccount(account1.getBalance());account2.deposit(500);System.out.println(account1.getBalance());System.out.println(account2.getBalance());
10001500
112
Preparare i casi di prova Come si può collaudare un programma?
– non è possibile provare tutti i possibili valori deidati in ingresso, e non avrebbe neanche senso farlo
– bisogna invece cercare di provare tutti i possibilicasi, i possibili gruppi di valori
– per far questo, bisogna predisporre dei casi diprova (test cases) per collaudare il programma
– bisogna anche verificare il funzionamento delprogramma nei casi di input non corretto
– per ogni caso di prova bisogna calcolaremanualmente l’output corretto del programma
113
Preparare i casi di prova (continua)
– per i casi di prova di input non corretto, bisognadeterminare le segnalazioni d’errore previste
– se il programma fallisce in un caso di prova, bisognaidentificare e correggere l’errore nel programma;quindi, bisogna eseguire di nuovo tutti i casi di prova
• correggendo un errore se ne possono introdurre altri!
– progettare i casi di prova prima di scrivere il codice• progettare i casi di prova aiuta a capire meglio l’algoritmo• dopo aver scritto il codice, si tende (inconsciamente?) a
collaudare di meno le parti di codice che si ritengono piùdeboli...
114
Errori di arrotondamento✔ Gli errori di arrotondamento sono un fenomeno
naturale nel calcolo in virgola mobile eseguito conun numero finito di cifre significative– calcolando 1/3 con due cifre significative, si ottiene 0,33– moltiplicando 0,33 per 3, si ottiene 0,99 e non 1
✔ Siamo abituati a valutare questi errori pensandoalla rappresentazione dei numeri in base decimale,ma i computer rappresentano i numeri in virgolamobile in base binaria e a volte si ottengono deirisultati inattesi!
Fondamenti di Informatica 1 Settimana 2
Marcello Dalpasso 20
115
Errori di arrotondamento
✔ Qui l’errore inatteso è dovuto al fatto che 4,35 nonha una rappresentazione esatta nel sistemabinario, proprio come 1/3 non ha unarappresentazione esatta nel sistema decimale– 4,35 viene rappresentato con un numero appena un po’
inferiore a 4,35, che, quando viene moltiplicato per 100,fornisce un numero appena un po’ inferiore a 435,quanto basta però per essere troncato a 434
✔ È sempre meglio usare Math.round
double f = 4.35;int n = (int)(100 * f);System.out.println(n);
434 ≠≠≠≠ 435
116
Guida in linea✔ Tutti gli ambienti di sviluppo Java forniscono
esaurienti sistemi di supporto (“guide in linea”),con cui è necessario prendere confidenza
✔ L’ambiente JDK fornisce tutta la documentazioneper l’utilizzo delle classi della libreria standard,alcuni documenti in formato “tutorial” per ladescrizione delle funzionalità di interi pacchetti edesempi di programmi (“demo”)
✔ È anche disponibile il codice sorgente di tutte leclassi della libreria standard, la cui lettura èinteressante e utile, anche se spesso complessa
117
Guida in linea✔ La descrizione di una classe comprende l’elenco
di tutti i suoi metodi pubblici (la sua interfaccia)ed una sintetica descrizione testuale dellemotivazioni alla base del progetto della classe edelle modalità suo utilizzo
✔ Per ogni metodo, vengono indicati– il nome e la funzionalità svolta– il tipo ed il significato dei parametri richiesti, se ci sono– il tipo ed il significato del valore restituito, se c’è– le eventuali eccezioni lanciate in caso di errore
118
��������������������������������
�������������������������