il tipo d i da ti ch ar (cap itolo 4) - home page | deiavanzini/fi1/slide/settimana03_2pp.pdf · so...

78
1 Il tipo di dati char (capitolo 4) SETTIMANA 3 2 Caratteri in una stringa Sappiamo già come estrarre sottostringhe da una stringa, con il metodo substring A volte è necessario estrarre ed elaborare sottostringhe di dimensioni minime, cioè di lunghezza unitaria una stringa di lunghezza unitaria contiene un solo carattere, che può essere memorizzato in una variabile di tipo char anziché in una stringa il tipo char in Java è un tipo di dato fondamentale come i tipi di dati numerici ed il tipo boolean, cioè non è una classe

Upload: vuongdien

Post on 21-Feb-2019

219 views

Category:

Documents


0 download

TRANSCRIPT

1

Il tipo di dati char(capitolo 4)

SETTIMANA 3

2

Caratteri in una stringaSappiamo già come estrarre sottostringhe da 

una stringa, con il metodo substringA volte è necessario estrarre ed elaborare 

sottostringhe di dimensioni minime, cioè di lunghezza unitaria una stringa di lunghezza unitaria contiene un solo 

carattere, che può essere memorizzato in una variabile di tipo char anziché in una stringa

il tipo char in Java è un tipo di dato fondamentale come i tipi di dati numerici ed il tipo boolean, cioè non è una classe

3

Caratteri in una stringa La presenza del tipo di dati char non è strettamente 

necessaria in Java (ed è anche per questo motivo che non l’avevamo ancora studiato) infatti, ogni elaborazione che può essere fatta su 

variabili di tipo char potrebbe essere fatta su stringhe di lunghezza unitaria

L’uso del tipo char per memorizzare stringhe di lunghezza unitaria è però importante, perché una variabile di tipo char occupa meno spazio in memoria 

di una stringa di lunghezza unitaria le elaborazioni su variabili di tipo char sono più veloci

4

Caratteri in una stringaIl metodo charAt della classe String restituisce il 

singolo carattere che si trova nella posizione indicata dal parametro ricevuto la convenzione sulla numerazione delle posizioni in 

una stringa è la stessa usata dal metodo substring

Una struttura di controllo che si usa spesso è l’elaborazione di tutti i caratteri di una stringa

String s = "John";char ch = s.charAt(2); // ch contiene 'h'

String s = "John";for (int i = 0; i < s.length(); i++){ char ch = s.charAt(i); // elabora ch}

5

Elaborazioni su variabili charCome si può elaborare una variabile di tipo char?Una variabile di tipo char può anche essere confrontata 

con una costante di tipo carattere una costante di tipo carattere è un singolo carattere 

racchiuso tra singoli apici (“apostrofo”)

Il carattere può anche essere una “sequenza di escape”

Una variabile carattere può essere stampata passandola a System.out.print o System.out.println

char ch = 'x';

char ch = '\u00E9'; // carattere 'è'char nl = '\n'; // carattere di "andata a capo"

char ch = 'x'; System.out.println(ch); // stampa 'x' e va a capo

6

Caratteri e l'operatore +Un char può essere concatenato ad una stringa con 

l’operatore di concatenazione + (viene convertito in stringa, con le stesse regole della conversione dei tipi numerici)

Se invece i due operandi di + sono entrambi caratteri Vengono automaticamente convertiti (“promossi”) in int L'operatore + indica una normale somma tra interi

char a = 'a';char b = 'b';int intc = a + b;char c = (char)(a + b);System.out.println(“intc: ” + intc);System.out.println(“c: “ + c);

intc: 195 c: Ã

7

Caratteri speciali e sequenze di “escape”

8

Sequenze di “escape” Proviamo a stampare una stringa che contiene delle 

virgolette

Il compilatore identifica le seconde virgolette come la fine della prima stringa "Hello, ", ma poi non capisce il significato della parola World

Basta inserire una barra rovesciata \ (backslash) prima delle virgolette all’interno della stringa

// NON FUNZIONA!System.out.println("Hello, "World"!");

Hello, "World"!

System.out.println("Hello, \"World\"!");

9

Sequenze di “escape”

Il carattere backslash all’interno di una stringa non rappresenta se stesso, ma si usa per codificare altri caratteri che sarebbe difficile inserire in una stringa, per vari motivi (sequenza di escape)

Allora, come si fa ad inserire veramente un carattere backslash in una stringa? si usa la sequenza di escape \\

// FUNZIONA!System.out.println("Hello, \"World\"!");

System.out.println("File C:\\autoexec.bat");

File C:\autoexec.bat

10

Sequenze di “escape”Un’altra sequenza di escape che si usa è \n, che 

rappresenta il carattere di “nuova riga” o “andare a capo”

Le sequenze di escape si usano anche per inserire caratteri di lingue straniere o simboli che non si trovano sulla tastiera

System.out.println("*\n**\n***");

******

System.out.println("*");System.out.println("**");System.out.println("***");

11

Sequenze di “escape”Ad esempio, per scrivere parole italiane con lettere 

accentate senza avere a disposizione una tastiera italiana

Queste sequenze di escape utilizzano la codifica standard Unicode ­ http://www.unicode.org per rappresentare i caratteri di tutti gli alfabeti del mondo con 4 cifre esadecimali (codifica a 16 bit, 65536 simboli diversi)

System.out.println("Perch\u00E9?");

Perché?

12

Escape e caratteri di controlloAlcune sequenze di escape possono essere usate per 

rappresentare dei caratteri di controllo Ovvero caratteri Unicode che non rappresentano 

simboli scritti Ma che fanno parte integrante di un flusso di testo, 

come tutti gli altri caratteriSEQ.ESCAPE NOME COD.UNICODE\n newline \u000A\t tab \u0009\b backspace \u0008\r return \u000D\f formfeed \u000C

13

Caratteri di controlloI primi 32 caratteri nella codifica Unicode sono tutti 

caratteri di controllo Il cosiddetto insieme C0 di ASCII (e Unicode) Per chi e' interessato

• http://en.wikipedia.org/wiki/C0_and_C1_control_codes

• http://en.wikipedia.org/wiki/Control_characterVedremo altri importanti caratteri di controllo

ETX (End­of­TeXt), immesso da tastiera con <CTRL>+C• usato per interrompere l'esecuzione di un programma

EOT (End­Of­Transmission, <CTRL>+D) e SUB (SUBstitute, <CTRL>+Z)

• Usati per segnalare la fine dell'input, ad esempio di un file 

14

Formattazione di numeri:il metodo printf

15

Formattazione di numeriNon sempre il formato standard per stampare numeri 

corrisponde ai nostri desideri

Ci piacerebbe di più visualizzare i numeri Con due cifre decimali Incolonnati

double total = 3.50;final double TAX_RATE = 8.5; // aliquota d’imposta in percentualedouble tax = total * TAX_RATE / 100;System.out.println(“Total: “ + total);System.out.println(“Tax: “ + tax); Total: 3.5

Tax: 0.2975

Total: 3.50Tax: 0.30

16

Formattazione di numeriJava fornisce il metodo printf, che ha più parametri 

espliciti Il primo parametro è una stringa di formato che 

contiene caratteri da stampare e specificatori di formato

• Ogni specificatore di formato comincia con il carattere % I parametri successivi sono i valori da visualizzare 

secondo i formati specificati

Produce:

System.out.printf(“Total:%5.2f”, total)

Total: 3.50

Spazio

17

Formattazione di numeriTipi di formato e modificatori di formato:

18

Caratteri di fine rigaDiversi sistemi operativi “capiscono” diversi caratteri di 

fine riga Sistemi Unix usano il carattere newline (o line­feed): \n DOS usa la sequenza carriagereturn­newline: \r\n

Per essere sicuri che la fine della riga sia riconosciuta da qualsiasi sistema operativo possiamo usare il metodo printf con il formato %n

produce Total: 3.50

System.out.printf(“Total:%5.2f%n”, total)

Nuova riga

19

Ricevere dati in ingresso

20

I dati in ingresso ai programmiI programmi visti finora non sono molto utili, visto 

che eseguono sempre la stessa elaborazione ad ogni esecuzione

Il programma Coins1 rappresenta sempre il medesimo borsellino… se si vuole che calcoli il valore contenuto in un 

diverso borsellino, è necessario modificare il codice sorgente (in particolare, le inizializzazioni delle variabili) e compilarlo di nuovo

I programmi utili hanno bisogno di ricevere dati in ingresso dall’utente

21

L’input standard dei programmiIl modo più semplice e immediato per fornire dati 

in ingresso ad un programma consiste nell’utilizzo della tastiera altri metodi fanno uso del mouse, del microfono…

Abbiamo visto che tutti i programmi Java hanno accesso al proprio output standard, tramite l’oggetto System.out di tipo PrintStream

Analogamente, l’interprete Java mette a disposizione dei programmi in esecuzione il proprio input standard (flusso di input), tramite l’oggetto System.in di tipo InputStream

22

La classe ScannerSfortunatamente, la classe InputStream non 

possiede metodi comodi per la ricezione di dati numerici e stringhe PrintStream ha invece il comodissimo metodo print

Per ovviare a questo inconveniente, Java 5.0 ha introdotto la classe Scanner Un oggetto di tipo Scanner consente di leggere da 

qualsiasi flusso di ingresso (ad es. un file) Noi cominciamo ad usarlo per leggere dati in ingresso 

da tastiera ricevuti tramite l'oggetto System.in

23

Leggere l’input con la classe Scanner

24

Scanner in = new Scanner(System.in);

Usare la classe Scanner Per leggere dallo standar input bisogna creare un oggetto di tipo 

Scanner, usando la sintassi consueta

Il parametro esplicito del costruttore di Scanner è System.in L'oggetto in di tipo Scanner è “agganciato” allo standard 

input Dato che la classe Scanner non fa parte del pacchetto 

java.lang, ma del pacchetto java.util, è necessario importare esplicitamente la classe all'interno del file java che ne fa uso 

Quando non si usa piu’ l’oggetto di classe Scanner e’ bene chiuderlo:

import java.util.Scanner;

in.close();

Sono due oggetti diversi!!

25

I metodi nextInt e nextDouble Come si fa ad acquisire valori numerici da standard input?Numero intero: metodo int nextInt()

Numero in virgola mobile: metodo double nextDouble()

Durante l’esecuzione del metodo (nextInt o nextDouble) il programma si ferma ed attende l’introduzione dell’input da tastiera, che termina quando l’utente batte il tasto Invio

nextInt restituisce un valore numerico di tipo int NextDouble restituisce un valore numerico di tipo double

• cosa succede se l’utente non digita un numero intero (o un numero double) sulla tastiera ?? Provare!!

int number = in.nextInt();

double number = in.nextDouble();

26

Esempioimport java.util.Scanner;

public class Coins4{ public static void main(String[] args) { Scanner in = new Scanner(System.in); System.out.println("Quante lire?"); int lit = in.nextInt(); System.out.println("Quanti euro?"); double euro = in.nextDouble(); System.out.print("Valore totale in euro "); System.out.println(euro + lit / 1936.27); }}

27

I metodi next e nextLineCome si fa ad acquisire stringhe da standard input?Parola 

ovvero una stringa delimitata dai caratteri di spaziatura space (SP), tab (\t), newline (\n), carriage­return (\r)

metodo String next()

Riga (ovvero una stringa delimitata dai caratteri \n o \r):  metodo String nextLine(): 

String city = in.nextLine();

String state = in.next();

28

Esempioimport java.util.Scanner;

public class MakePassword2{ public static void main(String[] args) { Scanner in = new Scanner(System.in); System.out.println("Inserire il nome"); String firstName = in.nextLine(); System.out.println("Inserire il cognome"); String lastName = in.nextLine(); System.out.println("Inserire l’eta’"); int age = in.nextInt(); String initials = firstName.substring(0, 1) + lastName.substring(0, 1); String pw = initials.toLowerCase() + age; System.out.println("La password e’ " + pw); }}

29

Scanner e localizzazioneLa classe Scanner prevede la possibilità di riconoscere 

numeri formattati secondo diverse “usanze locali” Nel corso noi useremo la convenzione anglosassone che 

prevede l’uso del carattere di separazione ‘.’ tra parte intera e parte frazionaria nei numeri in virgola mobile

Per definire un oggetto Scanner che rispetta questa convenzione dovremo importare anche la classe Locale e scrivere

import java.util.Scanner;import java.util.Locale;...Scanner in = new Scanner(System.in);in.useLocale(Locale.US);...

30

È tutto chiaro? …1.Perché non si possono leggere dati in ingresso 

direttamente tramite System.in ?2.Se in è un oggetto di tipo Scanner che legge da 

System.in e il nostro programma invocaString name = in.next();

Qual è il valore di name se l’utente digita la seguente stringa?John Q. Public

31

32

Realizzare classi(Capitolo 3)

33

Scatole nerePer molti guidatori

Un’automobile è una scatola nera Non sanno come funziona Ma sanno come usarla

Un ingegnere meccanico saprogettare una automobile ma noni moduli di controllo elettronico Non ne conosce il funzionamento interno Ma sa come usarli

Scatole nere danno luogo ad incapsulamento I dettagli non importanti vengono nascosti Ma va identificato il concetto che meglio rappresenta 

una scatola nera: questo comporta astrazione

34

Scatole nereApproccio alla programmazione

orientato agli oggettiIl software viene incapsulato in 

scatole nere (oggetti)

Diversi livelli di astrazione Un utente di computer usa un programma costruito 

tramite oggetti senza sapere nulla di programmazione  Un programmatore può usare un oggetto senza 

conoscerne i dettagli di funzionamento Gli oggetti usati da un programmatore sono 

programmati da... altri programmatori Un oggetto contiene... altri oggetti

35

Il progetto di una classe: BankAccount

36

Progettare la classe BankAccountVogliamo progettare la classe BankAccount, che 

descriva il comportamento di un conto corrente bancario

Quali caratteristiche sono essenziali al concetto di conto corrente bancario? Possibilità di versare denaro Possibilità di prelevare denaro Possibilità di conoscere il saldo attuale

Queste caratteristiche definiscono l'interfaccia pubblica della classe

37

Progettare la classe BankAccountLe operazioni consentite dal comportamento di un 

oggetto si effettuano mediante invocazione di metodiDobbiamo definire tre metodi

Tali metodi consentono di depositare denaro nel conto prelevare denaro dal conto conoscere il saldo

account.deposit(1000);

account.withdraw(500);

double balance = account.getBalance();

public void deposit(double amount);

public void withdraw(double amount);

public double getBalance();

38

Definizioni di metodi

La definizione di un metodo inizia sempre con la sua intestazione (o firma, o 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()

39

Definizioni di metodiL'intestazione di un metodo è seguita dal corpo del 

metodo stesso, composto da un insieme di enunciati che specificano le azioni svolte 

dal metodo stesso racchiusi tra parentesi graffe

public void deposit(double amount){

//corpo del metodo}

public double getBalance(){

//corpo del metodo}

40

Metodi di accesso e modificatori Metodo d'accesso: accede ad un oggetto e 

restituisce informazioni senza modificarlo getBalance è metodo di accesso length della classe String è metodo di accesso getX, getY, getWidth, getHeight della classe 

Rectangle sono metodi di accesso

Metodo modificatore: altera lo stato di un oggetto deposit e withdraw sono metodi modificatori translate della classe Rectangle è un metodo 

modificatore

41

Costruttori

42

Ripasso: costruire oggetti Abbiamo detto che per creare un nuovo oggetto di 

una classe si usa l’operatore new seguito dal nome della classe e da una coppia di parentesi tonde

L’operatore new crea un nuovo oggetto e ne restituisce un riferimento, assegnabile ad una variabile oggetto del tipo appropriato

new BankAccount();

BankAccount account = new BankAccount();

account BankAccount

43

I costruttoriNella realizzazione della classe BankAccount 

bisogna includere il codice per creare un nuovo conto bancario, ad esempio con saldo iniziale a zero.

Per consentire la creazione di un nuovo oggetto di una classe, inizializzandone lo stato, dobbiamo scrivere un nuovo metodo, il costruttore della classe

public BankAccount() { //corpo del costruttore }

I costruttori hanno sempre lo stesso nome della classe

44

I costruttoriSintassi:

Lo scopo principale di un costruttore è quello di inizializzare un oggetto della classe 

I costruttori, come i metodi, sono solitamente pubblici, per consentire a chiunque di creare oggetti 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 alcun valore e non 

bisogna neppure dichiarare che restituiscono void

tipoAccesso NomeClasse(TipoParametro nomeParametro,...) { //realizzazione del costruttore }

45

Invocazione di costruttoriI 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 e inizializzato quasi sempre il valore dell’operatore new viene 

memorizzato in una variabile oggettoBankAccount account = new BankAccount();// ora account ha saldo zero

new BankAccount();

46

Una classe con più costruttoriUna classe può avere più di un costruttoreAd esempio, definiamo un costruttore per creare un 

nuovo conto bancario con un saldo iniziale diverso da zero

public BankAccount() { // corpo del costruttore

// inizializza il saldo a 0 }public BankAccount(double initialBalance) { // corpo del costruttore

// inizializza il saldo a initialBalance }

47

Una classe con più costruttoriPer usare il nuovo costruttore di BankAccount, 

bisogna fornire il parametro initialBalance

Notiamo che, se esistono più costruttori in una classe, hanno tutti lo stesso nome, perché devono comunque 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 invocare basandosi sul numero e sul tipo dei parametri forniti nell’invocazione

BankAccount account = new BankAccount(500);

48

Una classe con più costruttoriIl compilatore effettua la risoluzione dell’ambiguità 

nell’invocazione di costruttori o metodi sovraccarichiSe non trova un costruttore che corrisponda ai 

parametri forniti nell’invocazione, segnala un errore semantico

// NON FUNZIONA!BankAccount a = new BankAccount("tanti soldi");

cannot resolve symbolsymbol     : constructor BankAccount (java.lang.String)location    : class BankAccount

49

Sovraccarico del nomeSe si usa lo stesso nome per metodi diversi, il nome 

diventa sovraccarico (nel senso di carico di significati 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 ben preciso per farlo (ed è bene farlo in questi casi)

• usare lo stesso nome per metodi diversi (che richiedono parametri di tipo diverso) sta ad indicare che viene compiuta la stessa elaborazione su tipi di dati diversi

50

Sovraccarico del nomeLa libreria standard di Java contiene numerosi 

esempi di metodi sovraccarichi

Quando si invoca un metodo sovraccarico, il compilatore risolve l’invocazione individuando quale sia il metodo richiesto sulla base dei parametri espliciti che vengono forniti

public class PrintStream{ ...

public void println(int n) {...} public void println(double d) {...} ...}

51

Definire una classe

52

Definizione di classeSintassi:

Le variabili di esemplare memorizzano lo stato di un oggetto La classe BankAccount deve avere un campo di 

esemplare che permetta di memorizzare il saldo di un oggetto di tipo BankAccount

tipoAccesso class nomeClasse { costruttori (intestazione e corpo)

metodi (intestazione e corpo)variabili (campi) di esemplare

}

53

Definire la classe BankAccountpublic class BankAccount{

//Costruttori public BankAccount() { corpo del costruttore }

public BankAccount(double initialBalance) { corpo del costruttore }

//Metodipublic void deposit(double amount)

{ realizzazione del metodo }

public void withdraw(double amount) { realizzazione del metodo }

public double getBalance() { realizzazione del metodo }

//Campi di esemplare ...}

54

È tutto chiaro? …1.Come si può svuotare il conto bancario account 

usando i metodi dell’interfaccia pubblica della classe?

2.Supponete di voler realizzare una più potente astrazione di conto bancario che tenga traccia anche di un numero di conto. Come va modificata l’interfaccia pubblica?

55

Variabili di esemplare

56

Lo stato di un oggettoGli oggetti (quasi tutti…) hanno bisogno di 

memorizzare il proprio stato attuale, cioè l’insieme dei valori che  descrivono l’oggetto e  influenzano (anche se non necessariamente) il 

risultato dell’invocazione dei metodi dell’oggetto

Gli oggetti della classe BankAccount hanno bisogno di memorizzare il valore del saldo del conto bancario che rappresentano

Lo stato di un oggetto viene memorizzato mediante variabili di esemplare (o “variabili di istanza”, instance variables)

57

Dichiarare variabili di esemplareSintassi:

Scopo: definire una variabile nomeVariabile di tipo TipoVariabile, una cui copia sia presente in ogni oggetto della classe NomeClasse

Esempio:

public class NomeClasse{ ... tipoDiAccesso TipoVariabile nomeVariabile; ...}

public class BankAccount{ ... private double balance; ...}

58

Variabili di esemplareCiascun oggetto (“esemplare”) della classe ha una 

propria copia delle variabili di esemplare

tra le quali non esiste nessuna relazione: possono essere modificate indipendentemente l’una dall’altra

account11000balance

BankAccount

account22000balance

BankAccount

59

Variabili di esemplareCosì come i metodi sono di solito “pubblici” (public), 

le variabili di esemplare sono di solito “private” (private)

Le variabili di esemplare private possono essere lette o modificate soltanto da metodi della classe a cui appartengono le variabili di esemplare private sono nascoste (hidden) 

al programmatore che utilizza la classe, e possono essere lette o modificate soltanto mediante l’invocazione di metodi pubblici della classe

questa caratteristica dei linguaggi di programmazione orientati agli oggetti si chiama incapsulamento o information hiding

60

IncapsulamentoPoiché la variabile balance di BankAccount è 

private, non vi si può accedere da metodi che non siano della classe (errore semantico segnalato dal compilatore)

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

61

IncapsulamentoL’incapsulamento ha molti vantaggi, soltanto pochi 

dei quali potranno essere evidenziati in questo corso di base

Il vantaggio fondamentale è quello di impedire l’accesso incontrollato allo stato di un oggetto, impedendo così anche che l’oggetto venga (accidentalmente o deliberatamente) posto in uno stato inconsistente Il progettista della classe BankAccount potrebbe 

definire (ragionevolmente) che soltanto un saldo non negativo rappresenti uno stato consistente per un conto bancario

62

IncapsulamentoDato che il valore di balance può essere modificato 

soltanto invocando i metodi deposit o withdraw, il progettista può impedire che diventi negativo, magari segnalando una condizione d’errore

Se invece fosse possibile assegnare direttamente un valore a balance dall’esterno, ogni sforzo del progettista di BankAccount sarebbe vano Si noti che, per lo stesso motivo e anche per realismo, 

non esiste un metodo setBalance, dato che il saldo di un conto bancario non può essere impostato ad un valore qualsiasi!

63

È tutto chiaro? …1.Si supponga di modificare la classe 

BankAccount in modo che ogni conto bancario abbia anche un numero di conto. Come si modificano i campi di esemplare?

2.Quali sono i campi di esemplare della classe Rectangle?

64

Realizzare costruttori e metodi

65

I metodi di BankAccountLa realizzazione dei costruttori e dei metodi di 

BankAccount è molto semplice lo stato dell’oggetto (il saldo del conto) è memorizzato 

nella variabile di esemplare balance i costruttori devono inizializzare la variabile balance quando si deposita o si preleva una somma di denaro, 

il saldo del conto si incrementa o si decrementa della somma specificata

il metodo getBalance restituisce il valore del saldo corrente memorizzato nella variabile balance

Per semplicità, questa realizzazione non impedisce che un conto assuma saldo negativo

66

I costruttori di BankAccount

public class BankAccount{

public BankAccount() {

balance = 0; }

public BankAccount(double initialBalance) {

balance = initialBalance; }

...}

67

Il costruttore predefinitoCosa 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• a false le variabili di tipo boolean• al valore speciale null le variabili oggetto, in modo che 

tali variabili non si riferiscano ad alcun oggetto

68

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;}

69

L’enunciato returnSintassi:

Scopo: terminare l’esecuzione di un metodo, ritornando all’esecuzione sospesa del metodo invocante se è presente una espressione, questa definisce il 

valore restituito dal metodo e deve essere del tipo dichiarato nella firma del metodo

Al termine di un metodo con valore restituito di tipo void, viene eseguito un return implicito il compilatore segnala un errore se si termina senza 

un enunciato return un metodo con un diverso tipo di valore restituito

return espressione;

return;

70

La classe BankAccount completapublic 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;}

71

È tutto chiaro? …1.Come è stato realizzato il metodo getWidth() 

della classe Rectangle?2.Come è stato realizzato il metodo translate della 

classe Rectangle?

72

Parametri espliciti/impliciti

73

I parametri dei metodi

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 suo parametro esplicito amount assume il valore 500 esplicito perché compare nella firma del metodo

A quale variabile balance si riferisce il metodo? si riferisce alla variabile che appartiene all’oggetto 

account con cui viene invocato il metodo account è il parametro implicito del metodo 

public void deposit(double amount){ balance = balance + amount;}

account.deposit(500);

74

Il riferimento null

75

Il riferimento nullUna variabile di un tipo numerico fondamentale 

contiene sempre un valore valido (eventualmente casuale, se non è stata inizializzata in alcun modo)

Una variabile oggetto può invece contenere esplicitamente un riferimento a nessun oggetto valido assegnando alla variabile il valore null, che è una parola chiave del linguaggio

vedremo in seguito applicazioni utili di questa proprietà in questo caso la variabile è comunque inizializzata

BankAccount account = null;

76

Il riferimento nullDiversamente dai valori numerici, che in Java non 

sono oggetti, le stringhe sono oggetti una variabile oggetto di tipo String può, quindi, 

contenere un riferimento null

String 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

77

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, segnalando un eccezione di tipo NullPointerException (pointer è un sinonimo di reference, “riferimento”)

78

Collaudare una classe

79

Usare la classe BankAccountSenza sapere come sia stata realizzata la classe 

BankAccount, siamo in grado di utilizzarla in un programma apriamo un nuovo conto bancario e depositiamo  un 

po’ di denaro

double initialDeposit = 1000;BankAccount account = new BankAccount();System.out.println("Saldo: " + account.getBalance());account.deposit(initialDeposit);System.out.println("Saldo: " + account.getBalance());

Saldo: 0Saldo: 1000

80

Usare la classe BankAccountTrasferiamo denaro da un conto ad un altro

Calcoliamo e accreditiamo gli interessi di un 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);

81

Classi di collaudoUsiamo la classe BankAccount per risolvere un 

problema specifico apriamo un conto bancario, saldo iniziale 10000 euro sul conto viene accreditato un interesse annuo del 5% del 

valore del saldo, senza fare prelievi né depositi qual è il saldo del conto dopo due anni?

BankAccount non contiene un metodo main Compilando BankAccount.java si ottiene BankAccount.class Ma non possiamo eseguire BankAccount.class

Dobbiamo scrivere una classe di collaudo (o di test) che contenga un metodo main nel quale Costruiamo uno o più oggetti della classe da collaudare Invochiamo i metodi della classe per questi oggetti Visualizziamo i valori restituiti

82

Esempio: utilizzo di BankAccountpublic class BankAccountTester{ 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"); }}

83

È tutto chiaro? …1.Quando eseguo BankAccountTester, quanti 

oggetti di tipo BankAccount vengono costruiti? E quanti di tipo BankAccountTester?

84

Un programma con più classiPer 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• Tutti i file vanno tenuti nella stessa cartella• Tutti i file vanno compilati separatamente• Solo la classe di collaudo (contenente il metodo main) va 

eseguita Scrivere tutte le classi in un unico file

• un file .java può contenere una sola classe public• la classe contenente il metodo main deve essere public• le altre non devono essere public (non serve scrivere 

private, semplicemente non si indica l’attributo public)• il file .java deve avere il nome della classe public

Nel compito faremo così!!

85

Riassunto: progettare una classe1. Capire cosa deve fare un oggetto della classe

Elenco in linguaggio naturale delle operazioni possibili

2. Specificare l'interfaccia pubblica Ovvero, definire i metodi tramite le loro intestazioni

3. Documentare l'interfaccia pubblica4. Identificare i campi di esemplare a partire dalle 

intestazioni dei metodi5. Realizzare costruttori e metodi

Se avete problemi a realizzare un metodo forse dovete riesaminare i passi precedenti

6. Collaudare la classe con un programma di collaudo

86

Materiale di complemento(capitolo 3)

87

Categorie e cicli di vita delle variabili

Per ora saltiamo questa sezione (3.7)• Ne parliamo più avanti (capitolo 9)

88

Parametri impliciti e il riferimento this

Per ora saltiamo questa sezione (3.8)• Ne parliamo più avanti (capitolo 9)

89

Commenti di documentazione

90

Commentare l'interfaccia pubblica I commenti ai metodi sono importantissimi per rendere il 

codice comprensibile a voi ed agli altri! Java ha delimitatori speciali per commenti di 

documentazione

@param nomeparametro per descrivere un parametro esplicito

@return per descrivere il valore restituito dal metodo

/** Preleva denaro dal conto @param amount importo da prelevare*/public void withdraw(double amount){

//corpo del metodo}

/** Ispeziona saldo attuale @return saldo attuale*/public double getBalance(){

//corpo del metodo}

91

Commentare l'interfaccia pubblicaInserire brevi commenti anche alla classe, per 

illustrarne lo scopo

Usando commenti di documentazione in questo formato si può generare in maniera automatica documentazione in html Genera un documento NomeClasse.html ben 

formattato e con collegamenti ipertestuali, contenente i commenti a NomeClasse

/** Un conto bancario ha un saldo modificabile tramite depositi e prelievi*/public class BankAccount{

...}

javadoc NomeClasse.java

92

93

Decisioni(capitolo 5)

94

L’enunciato ifIl programma precedente consente di prelevare tutto 

il denaro che si vuole il saldo balance può diventare negativo

È una situazione assai poco realistica!Il programma deve controllare il saldo ed agire di 

conseguenza, consentendo il prelievo oppure no

balance = balance - amount;

95

L’enunciato if

L’enunciato if si usa per realizzare una decisione ed è diviso in due parti una verifica un corpo

Il corpo viene eseguito se e solo se la verifica ha successo

if (amount <= balance) balance = balance - amount;

96

Tipi di enunciato in JavaEnunciato semplice

Enunciato composto

Blocco di enunciati

balance = balance - amount;

if (x >= 0) x=0;

{ zero o più enunciati di qualsiasi tipo }

97

Un nuovo problemaProviamo ora ad emettere un messaggio d’errore in 

caso di prelievo non consentito

Problema: se si modifica la prima verifica, bisogna ricordarsi di modificare anche la seconda (es. viene concesso un fido sul conto, che può “andare in rosso”)

Problema: se il corpo del primo if viene eseguito, la verifica del secondo if usa il nuovo valore di balance, introducendo un errore logico  quando si preleva più della metà del saldo disponibile

if (amount <= balance) balance = balance - amount;if (amount > balance) System.out.println("Conto scoperto");

98

La clausola elsePer realizzare un’alternativa, si utilizza la clausola 

else dell’enunciato if

Vantaggio: ora c’è una sola verifica se la verifica ha successo, viene eseguito il primo 

corpo dell’enunciato if/else altrimenti, viene eseguito il secondo corpo

if (amount <= balance) balance = balance - amount;else System.out.println("Conto scoperto");

99

if (amount <= balance) balance = balance - amount;else { System.out.println("Conto scoperto");

balance = balance – OVERDRAFT_PENALTY; }

La clausola else

100

L’enunciato ifSintassi:

Scopo: eseguire enunciato1 se e solo se la condizione è vera; se è presente la clausola else, eseguire enunciato2 se e solo se la condizione è falsa

Spesso il corpo di un enunciato if è costituito da più enunciati da eseguire in sequenza; racchiudendo tali enunciati tra una coppia di parentesi graffe { } si crea un blocco di enunciati, che può essere usato come corpo

if (condizione) enunciato1

if (condizione) enunciato1else enunciato2

if (amount <= balance){ balance = balance - amount; System.out.println("Prelievo accordato");}

101

È tutto chiaro? …1.Perché nell’esempio precedente abbiamo usato 

la condizione amount <= balance e non la condizione amount < balance?

2.Qual è l’errore logico nell’enunciato seguente, e come lo si può correggere?if (amount <= balance)

newBalance = balance – amount;balance = newBalance;

102

Confrontare valori numerici

103

Confrontare valoriLe condizioni dell’enunciato if sono molto spesso dei 

confronti tra due valori

Gli operatori di confronto si chiamano operatori relazionali

> Maggiore>= Maggiore o uguale< Minore<= Minore o uguale== Uguale!= Diverso

if (x >= 0)

Attenzione: negli operatori costituitida due caratteri nonvanno inseriti spaziintermedi

104

Operatori relazionaliFare molta attenzione alla differenza tra l’operatore 

relazionale == e l’operatore di assegnazione =

a = 5; // assegna 5 ad a

if (a == 5) // esegue enunciato enunciato // se a è uguale a 5

105

Confronto di numeri in virgola mobile

106

Confrontare numeri in virgola mobile

I numeri in virgola mobile hanno una precisione limitata ed i calcoli possono introdurre errori di arrotondamento e troncamento

Tali errori sono inevitabili e bisogna fare molta attenzione nella formulazione di verifiche che coinvolgono numeri in virgola mobile

double r = Math.sqrt(2);double x = r * r;if (x == 2)

System.out.println("OK");else

System.out.println("Non ci credevi?");

107

Confrontare numeri in virgola mobileAffinché gli errori di arrotondamento non influenzino 

la logica del programma, i confronti tra numeri in virgola mobile devono prevedere una tolleranza

Verifica di uguaglianza tra x ed y (di tipo double):| x ­ y | < ε         con ε = 1E­14

Scelta migliore se x,y sono molto grandi o molto piccoli| x ­ y | <   ε max(|x|,|y|)    con ε = 1E­14

(questo valore di   ε è ragionevole per numeri double) Il codice per questa verifica è

final double EPSILON = 1E-14;if ( Math.abs(x - y) <= EPSILON*Math.max(Math.abs(x),Math.abs(y)) )

...

108

Confrontare numeri in virgola mobilePossiamo definire un metodo statico che verifichi 

l’uguaglianza con tolleranza

public class Numeric{ public static boolean approxEqual(double x, double y) { final double EPSILON = 1E-14; double xyMax = Math.max(Math.abs(x),Math.abs(y));

return Math.abs(x - y) <= EPSILON * xyMax; }} double r = Math.sqrt(2);

if (Numeric.approxEqual(r * r, 2)) System.out.println("Tutto bene...");else System.out.println("Questo non succede...");

109

Confronto di stringhe

110

Confronto di stringhePer confrontare stringhe si usa il metodo equals

Per confrontare stringhe ignorando la differenza tra maiuscole e minuscole si usa

Non usare mai l’operatore di uguaglianza per confrontare stringhe! Usare sempre equals Se si usa l’operatore uguaglianza, il successo del 

confronto sembra essere deciso in maniera “casuale” In realtà dipende da come è stata progettata la Java 

Virtual Machine e da come sono state costruite le due stringhe

if (s1.equals(s2))

if (s1.equalsIgnoreCase(s2))

Attenzione perché NON è un errore di sintassi

111

Confronto di stringheConfrontando con l’operatore di uguaglianza due 

riferimenti a stringhe si verifica se i riferimenti puntano allo stesso oggetto stringa

Il confronto s1 == s2 è vero, perché puntano allo stesso oggetto stringa

Il confronto s1 == s3 è falso, perché puntano ad oggetti diversi, anche se tali oggetti hanno lo stesso contenuto (sono “identici”)

String s1 = "Stringa";String s2 = s1;String s3 = "String";s3 = s3 + "a"; // s3 contiene "Stringa"

112

Confronto di stringhe

Stringa

s1s2

s3

String s1 = "Stringa";String s2 = s1;String s3 = "String";s3 = s3 + "a";

String

Stringa

String

113

Confronto di stringheConfrontando invece con il metodo equals due 

riferimenti, si verifica se i riferimenti puntano ad stringhe con lo stesso contenuto

Il confronto s1.equals(s3) è vero, perché puntano a due oggetti String identici

Nota: per verificare se un riferimento si riferisce a null, bisogna usare invece l’operatore di uguaglianza e non il metodo equals

String s1 = "Stringa";String s2 = s1;String s3 = "String";s3 = s3 + "a"; // s3 contiene "Stringa"

if (s == null)

114

Ordinamento lessicograficoSe due stringhe sono diverse, è possibile conoscere 

la relazione che intercorre tra loro secondo l’ordinamento lessicografico, simile al comune ordinamento alfabetico

Il confronto lessicografico tra stringhe si esegue con il metodo compareTo

Il metodo compareTo restituisce un valore int  negativo se s1 precede s2 nell’ordinamento positivo se s1 segue s2 nell’ordinamento zero se s1 e s2 sono identiche 

if (s1.compareTo(s2) < 0)

115

Confronto lessicograficoPartendo dall’inizio delle stringhe, si confrontano i 

caratteri in posizioni corrispondenti, finché una delle stringhe termina oppure due caratteri sono diversi se una stringa termina, essa precede l’altra 

• se terminano entrambe, sono uguali altrimenti, l’ordinamento tra le due stringhe è uguale 

all’ordinamento alfabetico tra i due caratteri diversi

carta precede castano

c a atrc a ats on

lettereuguali r precede s

116

Confronto lessicograficoIl confronto lessicografico genera un ordinamento 

simile a quello di un comune dizionario…con qualche differenza… 

Tra i caratteri non ci sono solo le lettere• i numeri precedono le lettere• tutte le lettere maiuscole precedono tutte le lettere 

minuscole• il carattere di “spazio bianco” precede tutti gli altri 

caratteriL’ordinamento lessicografico è definito dallo standard 

Unicode, http://www.unicode.org

117

Confrontare oggetti

118

Confronto di oggettiCome per le stringhe, l’operatore == tra due variabili 

oggetto verifica se i due riferimenti puntano allo stesso oggetto, e non verifica l'uguaglianza tra oggetti

Il metodo equals può essere applicato a qualsiasi oggetto, perché è definito nella classe Object, da cui derivano tutte le classi

È compito di ciascuna classe ridefinire il metodo equals, come fa la classe String altrimenti il metodo equals di Object usa semplicemente 

l’operatore di uguaglianzaIl metodo equals di ciascuna classe deve effettuare il 

confronto delle caratteristiche (variabili di esemplare) degli oggetti di tale classe Per ora usiamo equals solo per classi della libreria standard non facciamo confronti tra oggetti di classi definite da noi

119

Ordinamento di oggettiIl metodo compareTo visto per le stringhe può 

essere applicato a molti altri oggetti, (ma non tutti perché non è definito nella classe Object)

È compito di ciascuna classe definire in maniera opportuna il metodo compareTo, come fa la classe String, secondo una opportuna nozione di ordinamento

Il metodo compareTo di una classe restituirà sempre un valore int  negativo se obj1 precede obj2 nell’ordinamento positivo se obj1 segue obj2 nell’ordinamento zero se obj1 e obj2 sono identici 

if (obj1.compareTo(obj2) < 0)

120

È tutto chiaro? …1. Qual è il valore di s.length() se s contiene (a) un 

riferimento alla stringa vuota “”   (b) un riferimento alla stringa “ “ contenente solo uno spazio (c) il valore null ?

2. Quali di questi confronti hanno errori di sintassi? Quali hanno poca utilità dal punto di vista logico?String a = “1”;String b = “one”;double x = 1;double y = 3 * (1.0 / 3);

(a) a == “1”; (b) a == null; (c) a.equals(“”); (d) a == b; (e) a == x; (f) x == y; (g) x – y == null; (h) x.equals(y);

121

Alternative multiple

122

Sequenza di confrontiSe si hanno più di due alternative, si usa una 

sequenza di confronti

if (richter >= 8) System.out.println("Terremoto molto forte");else if (richter >= 6) System.out.println("Terremoto forte");else if (richter >= 4) System.out.println("Terremoto medio");else if (richter >= 2) System.out.println("Terremoto debole");else if (richter >= 0) System.out.println("Terremoto molto debole");else System.out.println(“Numeri negativi non validi");

123

Sequenza di confrontiIl codice seguente non funziona, perché stampa 

“Terremoto molto debole” per qualsiasi valore di richter

Se si fanno confronti di tipo “maggiore di” si devono scrivere prima i valori più alti, e viceversaif (richter >= 0) // NON FUNZIONA! System.out.println("Terremoto molto debole");else if (richter >= 2) System.out.println("Terremoto debole");else if (richter >= 4) System.out.println("Terremoto medio");else if (richter >= 6) System.out.println("Terremoto forte");else System.out.println("Terremoto molto forte");

124

Sequenza di confrontiSe non si rendono mutuamente esclusive le 

alternative, usando le clausole else, non funziona se richter vale 3, stampa sia “Terremoto debole” sia 

“Terremoto molto debole”

if (richter >= 8) // NON FUNZIONA! System.out.println("Terremoto molto forte");if (richter >= 6) System.out.println("Terremoto forte");if (richter >= 4) System.out.println("Terremoto medio");if (richter >= 2) System.out.println("Terremoto debole");if (richter >= 0) System.out.println("Terremoto molto debole");

125

Diramazioni annidate

126

Diramazioni annidateAliquote per categorie d’imposta federali (1992)

Per semplicità usiamo il sistema fiscale americano e non quello italiano 

Ci sono due livelli nel processo decisionale Prima dobbiamo scegliere lo stato civile Poi, per ciascuno stato civile, dobbiamo scegliere lo 

scaglione di reddito

127

Diramazioni annidateUsiamo due diramazioni annidate

un enunciato if  all’interno del corpo di un altro enunciato if

if (status == SINGLE){ if (income <= SINGLE_BRACKET1)

...else if (income <= SINGLE_BRACKET2)

...else

...}else{ if (income <= MARRIED_BRACKET1)

...else if (income <= MARRIED_BRACKET2)

...else

...}

128

Diramazioni annidate

129

È tutto chiaro? …1.L’enunciato if/else/else per la scala Richter 

verifica prima i valori più elevati. Si può invertire l’ordine delle verifiche?

2.Alcuni contestano l’applicazione di aliquote più elevate ai redditi più elevati perché dopo aver pagato le tasse si potrebbe rimanere con meno soldi pur avendo guadagnato di più. Dove è l’errore in questo ragionamento?

130

Il problema dell’else sospeso

131

Il problema dell’else sospeso

Nell’esempio seguente i livelli di rientro suggeriscono che la clausola else si riferisca al primo enunciato if ma il compilatore ignora i rientri!

La regola sintattica è che una clausola else appartiene sempre all’enunciato if più vicinodouble cost = 5; // prezzo per USAif (country.equals("USA")) if (state.equals("HI")) cost = 10; // Hawaii più costosoelse // NON FUNZIONA! cost = 20; // estero ancora più costoso

132

Il problema dell’else sospesoL’esempio precedente svolge in realtà la funzione 

evidenziata dai rientri seguenti

Il risultato è che gli stati esteri ottengono il prezzo più basso, e gli USA continentali il più alto! Il contrario di ciò che si voleva...

double cost = 5; // prezzo per esteroif (country.equals("USA")) if (state.equals("HI")) cost = 10; // Hawaii più costoso else cost = 20; // USA ancora più costoso

133

Il problema dell’else sospesoPer ottenere il risultato voluto, bisogna “nascondere” 

il secondo enunciato if all’interno di un blocco di enunciati, inserendo una coppia di parentesi graffe per evitare problemi con l’else sospeso, è meglio 

racchiudere sempre il corpo di un enunciato if tra parentesi graffe, anche quando sono inutili

double cost = 5; // prezzo per USAif (country.equals("USA")){ if (state.equals("HI")) cost = 10; // Hawaii più costoso}else cost = 20; // estero ancora più costoso

134

Espressioni booleane

135

Il tipo di dati booleanoOgni espressione in Java ha un valore

x + 10   espressione aritmetica, valore numerico x < 10   espressione relazionale, valore booleano

Un’espressione relazionale può avere solo due valori:  vero o falso (true o false)

I valori true e false non sono numeri, né oggetti, né classi: appartengono ad un tipo di dati diverso, detto booleano è un tipo fondamentale in Java, come quelli numerici Il nome deriva da quello del matematico George Boole 

(1815­1864), pioniere della logica

136

Le variabili booleaneIl tipo di dati boolean, come tutti gli altri tipi di dati, 

consente la definizione di variabiliA volte è comodo utilizzare variabili booleane per 

memorizzare valori di passaggi intermedi in cui è opportuno scomporre verifiche troppo complesse

Altre volte l’uso di una variabile booleana rende più leggibile il codice

Spesso le variabili booleane vengono chiamate flags (bandiere), perché possono assumere soltanto due valori, cioè trovarsi in due soli stati possibili: su e giù, come una bandiera

137

Metodi predicativiCosì vengono chiamati metodi che restituiscono valori 

di tipo booleano Solitamente verificano una condizione sullo stato di un 

oggetto Solitamente iniziano con “is” oppure “has”

La classe Character contiene metodi predicativi statici isDigit, isLetter, isUpperCase, isLowerCase

La classe Scanner contiene metodi predicativi per verificare il contenuto dell’input: hasNextInt, hasNextDouble, …

Metodi predicativi possono essere usati come condizioni di enunciati ifif (Character.isUpperCase(ch))// esegue se il carattere ch è maiuscolo

138

Operatori booleani

139

Gli operatori booleani o logiciGli operatori booleani o logici servono a svolgere 

operazioni su valori booleani

L’operatore && (and, e) combina due o più condizioni in una sola, che risulta vera se e solo se sono tutte vere

L’operatore || (or, oppure) combina due o più condizioni in una sola, che risulta vera se e solo se almeno una è vera

L’operatore ! (not, non) inverte il valore di un’espressione booleana 

if (x > 10 && x < 20)// esegue se x è maggiore di 10 e minore di 20

140

Gli operatori booleani o logiciPiù operatori booleani possono essere usati in 

un’unica espressione

La valutazione di un’espressione con operatori booleani viene effettuata con una strategia detta cortocircuito (o valutazione pigra) la valutazione dell’espressione termina appena è 

possibile decidere il risultatonel caso precedente, se x vale 15, l’ultima condizione 

non viene valutata, perché sicuramente l’intera espressione è vera

if ((x > 10 && x < 20) || x > 30)

141

Gli operatori booleani o logiciA B A && B

true true truetrue false falsefalse qualsiasi false

A B A || Btrue qualsiasi truefalse true truefalse false false

A !Atrue falsefalse true

142

Gli operatori booleani o logiciIn un’espressione booleana con più operatori, la 

valutazione viene fatta da sinistra a destra, dando la precedenza all’operatore not, poi all’operatore and, infine all’operatore or

L’ordine di valutazione può comunque essere alterato dalle parentesi tonde

if (!(x < 0 || x > 10))// esegue se x è compreso tra 0 e 10,// estremi inclusi

if (!x < 0 || x > 10)// esegue se x è maggiore o uguale a 0

143

È tutto chiaro? …1.In quali condizioni il seguente enunciato 

visualizza “false”?System.out.println(x > 0 || x < 0);

2.Riscrivere l’espressione seguente evitando di effettuare il confronto con il valore falseif (Character.isDigit(ch) == false)

144

Leggi di De MorganStabiliscono un criterio per convertire un’espressione 

“negata” in una espressione “affermata”

Gli operatori not vengono spostati su ciascuna delle espressioni coinvolte

Gli operatori and e gli operatori or vengono scambiati

Queste due espressioni sono equivalenti (abbiamo usato la seconda legge di De Morgan)

if (!(x < 0 || x > 10))

if ( x >0 && x <= 10 )

145

146

Materiale di complemento(Capitolo 6)

147

L’enunciato switch

148

L’enunciato switch Una sequenza che confronti un’unica variabile intera 

con diverse alternative costanti può essere realizzata con un enunciato switch

int x;int y;...if (x == 1) y = 1;else if (x == 2) y = 4;else if (x == 4) y = 16;else y = 0;

int x;int y;...switch (x){ case 1: y = 1; break; case 2: y = 4; break; case 4: y = 16; break; default: y = 0; break;}

149

L’enunciato switchVantaggio: non bisogna ripetere il nome 

della variabile da confrontareSvantaggio: non si può usare se la variabile 

da confrontare non è interaSvantaggio: non si può usare se uno dei 

valori da confrontare non è costanteSvantaggio: ogni case deve terminare con 

un enunciato break, altrimenti viene eseguito anche il corpo del case successivo! Questo è fonte di molti errori...

150

Consigli utili

151

Errori con operatori relazionaliAlcune espressioni “naturali” con operatori relazionali 

sono errate, ma per fortuna il compilatore le rifiuta

Perché il compilatore le rifiuta?

if (0 <= x <= 1) // NON FUNZIONA!

if (0 <= x && x <= 1) // OK

if (x && y > 0) // NON FUNZIONA!

if (x > 0 && y > 0) // OK

152

Errori con operatori relazionaliIl compilatore analizza l’espressione logica e trova 

due operatori di confronto, quindi esegue il primo da sinistra e decide che il risultato sarà un valore booleano

Successivamente, si trova a dover applicare il secondo operatore relazionale a due operandi, il primo dei quali è di tipo boolean, mentre il secondo è di tipo int

if (0 <= x <= 1) x++; // NON FUNZIONA!

operator <= cannot be applied to boolean,intif (0 <= x <= 10) x++; ^1 error

153

Errori con operatori relazionaliIl compilatore analizza l’espressione logica e trova un 

operatore di confronto (che ha la precedenza sull’operatore booleano && ), il cui risultato sarà un valore di tipo boolean

Successivamente, si trova ad applicare l’operatore booleano && a due operandi, il primo dei quali è di tipo int, mentre il secondo è di tipo boolean

if (x && y > 0) x++; // NON FUNZIONA!

operator && cannot be applied to int,booleanif (x && y > 0) x++; ^1 error

154

Rientri e TabulazioniDecidere il numero ideale di caratteri bianchi da usare 

per ogni livello di rientro è molto arduoIn questo corso consigliamo di usare tre/quattro 

caratteri

Consigliamo anche di non usare i “caratteri di tabulazione”, che di solito generano un rientro di otto caratteri, eccessivo

if (amount <= balance){ balance = balance - amount; if (amount > 20000000) { System.out.println("Esagerato!"); }}

155

Disposizione delle graffeIncolonnare le parentesi 

graffe

Eventualmente lasciare su una riga da sola anche la graffa aperta

Evitare questa disposizione è più difficile trovare la 

coppia!

if (...){ ...; ...;}

if (...){ ...; ...;}

if (...) { ...; ...;}