Esercizi
- Home
- Esercizi Capitolo 2
Capitolo 2
Componenti fondamentali di un programma Java
Ricordiamo che molti esercizi sono propedeutici ai successivi, quindi non
conviene saltarne qualcuno o quantomeno vi consigliamo di consultare le soluzioni prima di andare avanti.
Di seguito trovate gli esercizi del capitolo. Per
ogni esercizio, cliccando sulla traccia potete vedere la
relativa soluzione.
Gli esercizi caratterizzati dall'icona sono
considerati i più complessi
relativamente agli argomenti trattati.
Se preferite lavorare offline, è possibile scaricare tutti gli esercizi e le relative
soluzioni in formato PDF nella sezione download.
-
Esercizio 2.a)
Viene fornita (copiare, salvare e compilare) la seguente classe:
public class NumeroIntero { public int numeroIntero; public void stampaNumero() { System.out.println(numeroIntero); } }
Questa classe definisce il concetto di numero intero come oggetto. In essa vengono dichiarati una variabile intera ed un metodo che stamperà la variabile stessa. Scrivere, compilare ed eseguire una classe che:
1. istanzierà almeno due oggetti dalla classe
NumeroIntero
(contenente un metodomain
);
2. cambierà il valore delle relative variabili e testerà la veridicità delle avvenute assegnazioni, sfruttando il metodostampaNumero
;
3. aggiungerà un costruttore alla classeNumeroIntero
che inizializzi la variabile d’istanza.
Due domande ancora:4. a che tipologia di variabili appartiene la variabile
numeroIntero
definita nella classeNumeroIntero
?
5. Se istanziamo un oggetto della classeNumeroIntero
, senza assegnare un nuovo valore alla variabilenumeroIntero
, quanto varrà quest’ultima?
Soluzione
Di seguito viene listata una classe che aderisce ai requisiti richiesti:
public class ClasseRichiesta { public static void main (String args []) { NumeroIntero uno = new NumeroIntero(); NumeroIntero due = new NumeroIntero(); uno.numeroIntero = 1; due.numeroIntero = 2; uno.stampaNumero(); due.stampaNumero(); } }
Inoltre un costruttore per la classeNumeroIntero
potrebbe impostare l’unica variabile d’istanzanumeroIntero
:
public class NumeroIntero { public int numeroIntero; public NumeroIntero(int n) { numeroIntero = n; } public void stampaNumero() { System.out.println(numeroIntero); } }
In tal caso, però, per istanziare oggetti dalla classeNumeroIntero
, non sarà più possibile utilizzare il costruttore di default (che non sarà più inserito dal compilatore). Quindi la seguente istruzione produrrebbe un errore in compilazione:
NumeroIntero uno = new NumeroIntero();
Bisogna invece creare oggetti passando al costruttore direttamente il valore della variabile da impostare, per esempio:
NumeroIntero uno = new NumeroIntero(1);
Risposte alle ultime due domande:
4. Trattasi di una variabile d’istanza, perché dichiarata all’interno di una classe, al di fuori di metodi.
5. Il valore sarà zero, ovvero il valore nullo per una variabile intera. Infatti, quando si istanzia un oggetto, le variabili d’istanza vengono inizializzate ai valori nulli se non esplicitamente inizializzate ad altri valori. -
Esercizio 2.b) Concetti sui componenti fondamentali,
Vero o Falso:
1. Una variabile d’istanza deve essere per forza inizializzata dal programmatore.
2. Una variabile locale condivide il ciclo di vita con l’oggetto in cui è definita.
3. Un parametro ha un ciclo di vita coincidente con il metodo in cui è dichiarato: nasce quando il metodo viene invocato, muore quando termina il metodo.
4. Una variabile d’istanza appartiene alla classe in cui è dichiarata.
5. Un metodo è sinonimo di azione, operazione.
6. Sia le variabili sia i metodi sono utilizzabili di solito mediante l’operatore dot, applicato ad un’istanza della classe dove sono stati dichiarati.
7. Un costruttore è un metodo che non restituisce mai niente, infatti ha come tipo di ritornovoid
.
8. Un costruttore viene detto di default, se non ha parametri.
9. Un costruttore è un metodo e quindi può essere utilizzato mediante l’operatore dot, applicato ad un’istanza della classe dove è stato dichiarato.
10. Un package è fisicamente una cartella che contiene classi, le quali hanno dichiarato esplicitamente di far parte del package stesso nei rispettivi file sorgente.
Soluzione
1. Falso, una variabile locale deve essere per forza inizializzata dal programmatore.
2. Falso, una variabile d’istanza condivide il ciclo di vita con l’oggetto a cui appartiene.
3. Vero.
4. Falso, una variabile d’istanza appartiene ad un oggetto istanziato dalla classe in cui è dichiarata.
5. Vero.
6. Vero.
7. Falso, un costruttore è un metodo che non restituisce mai niente, infatti non ha tipo di ritorno.
8. Falso, un costruttore viene detto di default se viene inserito dal compilatore. Inoltre non ha parametri, ma non tutti i costruttori di default non hanno parametri.
9. Falso, un costruttore è un metodo speciale che ha la caratteristica di essere invocato una ed una sola volta nel momento in cui si istanzia un oggetto.
10. Vero.
-
Esercizio 2.c) Sintassi dei componenti fondamentali.
Vero o Falso:
1. Nella dichiarazione di un metodo (non costruttore), il nome è sempre seguito dalle parentesi che circondano i parametri opzionali, ed è sempre preceduto da un tipo di ritorno.
2. Il seguente metodo è dichiarato in maniera corretta:
public void metodo() { return 5;
}3. Il seguente metodo è dichiarato in maniera corretta:
public int metodo() { System.out.println("Ciao");
}4. La seguente variabile è dichiarata in maniera corretta:
public int a = 0;
5. La seguente variabile
x
è utilizzata in maniera corretta (fare riferimento alla classePunto
definita in questo capitolo):Punto p1 = new Punto(); Punto.x = 10;
6. La seguente variabile
x
è utilizzata in maniera corretta (fare riferimento alla classePunto
definita in questo capitolo):Punto p1 = new Punto(); Punto.p1.x = 10;
7. La seguente variabile
x
è utilizzata in maniera corretta (fare riferimento alla classePunto
definita in questo capitolo):Punto p1 = new Punto(); x = 10;
8. Il seguente costruttore è utilizzato in maniera corretta (fare riferimento alla classe
Punto
definita in questo capitolo):Punto p1 = new Punto(); p1.Punto();
9. Il seguente costruttore è dichiarato in maniera corretta:
public class Computer { public void Computer(){ } }
10. Il seguente costruttore è dichiarato in maniera corretta:
public class Computer { public computer(int a) { } }
Soluzione
1. Vero.
2. Falso, tenta di restituire un valore intero ma possiede tipo di ritornovoid
.
3. Falso, il metodo dovrebbe restituire un valore intero.
4. Vero.
5. Falso, l’operatore dot deve essere applicato all’oggetto e non alla classe:
Punto p1 = new Punto(); p1.x = 10;
7. Falso, l’operatore dot deve essere applicato all’oggetto. Il compilatore non troverebbe infatti la dichiarazione della variabilex
.
8. Falso, un costruttore è un metodo speciale che ha la caratteristica di essere invocato una ed una sola volta nel momento in cui si istanzia un oggetto.
9. Falso, il costruttore non dichiara tipo di ritorno e deve avere nome coincidente con la classe.
10. Falso, il costruttore deve avere nome coincidente con la classe.
-
Esercizio 2.d)
Creare una classe
Quadrato
, che dichiari una variabile d’istanza interalato
. Quindi creare un metodo pubblico che si chiamiperimetro
e che ritorni il perimetro del quadrato, e un metodo pubblicoarea
che ritorni l’area del quadrato.Ricordiamo per chi lo ha dimenticato, che il perimetro è la somma dei lati del quadrato, mentre l’area si calcola moltiplicando il lato per sé stesso. Infine ricordiamo che il simbolo per eseguire una moltiplicazione in Java è il*
.
Soluzione
Il listato dovrebbe essere simile al seguente:
public class Quadrato { public int lato; public int perimetro() { int perimetro = lato * 4; return perimetro; } public int area() { int area = lato * lato; return area; } }
-
Esercizio 2.e)
Creare una classe
TestQuadrato
che contenga un metodomain
che istanzi un oggetto di tipoQuadrato
, con lato di valore5
. Quindi stampare il perimetro e l’area dell’oggetto appena creato.
Soluzione
Il listato dovrebbe essere simile al seguente:
public class TestQuadrato { public static void main(String args[]) { Quadrato quadrato = new Quadrato(); quadrato.lato = 5; int perimetro = quadrato.perimetro(); System.out.println(perimetro); int area = quadrato.area(); System.out.println(area); } }
Si noti che abbiamo creato le variabili localiperimetro
earea
con lo stesso nome del metodo, e questo non è un problema. Infatti il nome di un metodo si differenzia sempre dal nome di una variabile perché dichiarato con parentesi tonde. Avremmo anche potuto chiamare in modo diverso le variabili, ma è buona norma che i nomi siano auto-esplicativi. Tuttavia potevamo anche evitare completamente l’uso di queste variabili se avessimo scritto la classe in questo modo:
public class TestQuadrato { public static void main(String args[]) { Quadrato quadrato = new Quadrato(); quadrato.lato = 5; System.out.println(quadrato.perimetro()); System.out.println(quadrato.area()); } }
Il codice è più compatto, ma almeno all’inizio conviene utilizzare le variabili per meglio memorizzare le definizioni. -
Esercizio 2.f)
Dopo aver svolto l’esercizio precedente, dovreste aver impostato la variabile
lato
a mano con un'istruzione come la seguente:
nomeOggetto.lato = 5;
Per poter evitare questa istruzione si crei un costruttore nella classe
Quadrato
dell’esercizio 2.d, che prenda in input il valore della variabilelato
. Dopo aver finito, si compili la classeQuadrato
. La classeTestQuadrato
invece, non compilerà più per via dell’istruzione specificata sopra e per il mancato utilizzo del nuovo costruttore. Si modifichi il codice della classeTestQuadrato
in modo tale che compili e sia eseguita correttamente.
Soluzione
Il listato della classe
Quadrato
dovrebbe essere simile al seguente:
public class Quadrato { public int lato; public Quadrato(int l) { lato = l; } public int perimetro() { int perimetro = lato * 4; return perimetro; } public int area() { int area = lato * lato; return area; } }
Il listato della classeTestQuadrato
modificato dovrebbe invece essere:
public class TestQuadrato { public static void main(String args[]) { Quadrato quadrato = new Quadrato(5); int perimetro = quadrato.perimetro(); System.out.println(perimetro); int area = quadrato.area(); System.out.println(area); } }
-
Esercizio 2.g)
Nella classe
Quadrato
creata nell’esercizio 2.d, sostituire il valore4
usato per calcolare il perimetro, con una costante d’istanzaNUMERO_LATI
.Si noti che per la costante è stato usato un nome costituito da sole lettere maiuscole separate con un simbolo di sottolineatura (underscore). Questa è una convenzione che si usa per le costanti, come spiegato nel paragrafo 3.1.Questo non dovrebbe influire sulla classe
TestQuadrato
.
Soluzione
Il listato potrebbe essere simile a:
public class Quadrato { public final int NUMERO_LATI = 4; public int lato; public int perimetro() { int perimetro = lato * NUMERO_LATI; return perimetro; } public int area() { int area = lato * lato; return area; } }
-
Esercizio 2.h)
Creare una classe
Rettangolo
, equivalente alla classeQuadrato
creata nell’esercizio 2.d e perfezionata negli esercizi successivi. Prima di codificare la classe decidere che specifiche deve avere questa classe (variabili e metodi).Mai "buttarsi sul codice" direttamente. È un errore classico che soprattutto all’inizio può portare a perdersi. Bisogna prima definire nella propria mente, o ancora meglio su un foglio di carta, le specifiche. Il consiglio è quello di avere ben chiare le varie definizioni (variabili d’istanza, variabili locali, metodi, costruttori etc.).
Soluzione
Il listato per la classe
Rettangolo
potrebbe essere il seguente:
public class Rettangolo { public final int NUMERO_LATI_UGUALI = 2; public int base; public int altezza; public Rettangolo(int b, int h) { base = b; altezza = h; } public int perimetro() { int perimetro = (base + altezza) * NUMERO_LATI_UGUALI; return perimetro; } public int area() { int area = base * altezza; return area; } }
-
Esercizio 2.i)
Creare una classe
TestRettangolo
che contenga un metodomain
e che testi la classeRettangolo
, equivalentemente a come abbiamo fatto nell’esercizio 2.f. Questa volta si istanzino almeno due rettangoli diversi.
Soluzione
Il listato per la classe
TestRettangolo
potrebbe essere il seguente:
public class TestRettangolo { public static void main(String args[]) { Rettangolo rettangolo1 = new Rettangolo(5,6); Rettangolo rettangolo2 = new Rettangolo(8,9); System.out.println("Perimetro del rettangolo 1 = " + rettangolo1.perimetro()); System.out.println("Area del rettangolo 1 = " + rettangolo1.area()); System.out.println("Perimetro del rettangolo 2 = " + rettangolo2.perimetro()); System.out.println("Area del rettangolo 2 = " + rettangolo2.area()); } }
-
Esercizio 2.j)
Aggiungere alle classi
Quadrato
eRettangolo
create negli esercizi precedenti, un metodo chiamatostampaDettagli
, che stampa i dettagli della figura geometrica in questione, compresi perimetro e area. Creare anche una nuova versione delle classiTestQuadrato
eTestRettangolo
che richiamino direttamente i metodistampaDettagli
sugli oggetti istanziati.
Soluzione
Il codice della classe
Quadrato
potrebbe essere il seguente:
public class Quadrato { public final int NUMERO_LATI = 4; public int lato; public Quadrato(int l) { lato = l; } public int perimetro() { int perimetro = lato * NUMERO_LATI; return perimetro; } public int area() { int area = lato * lato; return area; } public void stampaDettagli(){ System.out.println("Questo quadrato, ha lato = " + lato + ", perimetro = " + perimetro()+ ", area = " + area()); } }
Il codice della classeRettangolo
potrebbe essere il seguente:
public class Rettangolo { public final int NUMERO_LATI_UGUALI = 2; public int base; public int altezza; public Rettangolo(int b, int h) { base = b; altezza = h; } public int perimetro() { int perimetro = (base + altezza ) * NUMERO_LATI_UGUALI; return perimetro; } public int area() { int area = base * altezza; return area; } public void stampaDettagli(){ System.out.println("Questo rettangolo, ha base = " + base + ", altezza = " + altezza + ", perimetro = " + perimetro()+ ", area = " + area()); } }
Il codice della classeTestQuadrato
potrebbe essere il seguente (notare come il codice sia più semplice, breve e leggibile):
public class TestQuadrato { public static void main(String args[]) { Quadrato quadrato = new Quadrato(5); quadrato.stampaDettagli(); } }
Stesso discorso per la classeTestRettangolo
, il cui codice potrebbe essere il seguente:
public class TestRettangolo { public static void main(String args[]) { Rettangolo rettangolo1 = new Rettangolo(5,6); Rettangolo rettangolo2 = new Rettangolo(8,9); rettangolo1.stampaDettagli(); rettangolo2.stampaDettagli(); } }
-
Esercizio 2.k)
Partendo dalla soluzione dell’esercizio precedente, creare un ulteriore metodo nelle classi
Quadrato
eRettangolo
, chiamatodammiDettagli
, che restituisce la stessa stringa che veniva stampata nel metodostampaDettagli
. Dopo averlo creato, fare in modo che il metodostampaDettagli
, sfrutti il metododammiDettagli
in modo tale da non duplicare il codice. Creare una classe chiamataTestQuadrilateri
che stampa i dettagli di un quadrato e di un rettangolo.
Soluzione
Il codice della classe
Quadrato
potrebbe essere il seguente:
public class Quadrato { public final int NUMERO_LATI = 4; public int lato; public Quadrato(int l) { lato = l; } public int perimetro() { int perimetro = lato * NUMERO_LATI; return perimetro; } public int area() { int area = lato * lato; return area; } public void stampaDettagli(){ System.out.println(dammiDettagli()); } public String dammiDettagli(){ return "Questo quadrato, ha lato di lunghezza = " + lato + ", perimetro = " + perimetro()+ ", area = " + area(); } }
Con lo stesso criterio potremmo modificare la classeRettangolo
con il seguente codice:
public class Rettangolo { public final int NUMERO_LATI_UGUALI = 2; public int base; public int altezza; public Rettangolo(int b, int h) { base = b; altezza = h; } public int perimetro() { int perimetro = (base + altezza ) * NUMERO_LATI_UGUALI; return perimetro; } public int area() { int area = base * altezza; return area; } public void stampaDettagli(){ System.out.println(dammiDettagli()); } public String dammiDettagli(){ return "Questo rettangolo, ha base = " + base + ", altezza = " + altezza + ", perimetro = " + perimetro()+ ", area = " + area(); } }
Il codice della classeTestQuadrilateri
potrebbe essere il seguente:
public class TestQuadrilateri { public static void main(String args[]) { Quadrato quadrato = new Quadrato(5); quadrato.stampaDettagli(); Rettangolo rettangolo = new Rettangolo(5,6); rettangolo.stampaDettagli(); } }
-
Esercizio 2.l)
Si astragga con una classe il concetto di
Nazione
, creando almeno un costruttore e delle variabili d’istanza, ma nessun metodo.
Soluzione
Il listato per la classe
Nazione
potrebbe essere il seguente:
public class Nazione { public String nome; public String capitale; public int popolazione; public Nazione(String n, String c, int p) { nome = n; capitale = c; popolazione = p; } }
L’astrazione, pur essendo molto generica sembra corretta. L’unico costruttore definito implica la specificazione in fase di istanza dei tre parametri in input, che abbiamo quindi imposto essere obbligatori. Infatti quando istanziamo un oggetto Nazione, dobbiamo specificare i parametri di input del costruttore:
Nazione italia = new Nazione("Italia", "Roma", "60000000");
Non si doveva obbligatoriamente creare una classe con le stesse variabili, l’importante è avere una propria astrazione corretta. -
Esercizio 2.m)
Dopo aver creato la classe
Nazione
dell’esercizio 2.l, riuscite a creare uno o più metodi? Se ci riuscite, definiteli all’interno della classe. Se non ci riuscite, sapete spiegare il perché?
Soluzione
È possibile che qualcuno sia riuscito a creare dei metodi all’interno di questa classe. Nell’esercizio precedente è stata richiesta solo in modo generico un’astrazione della classe
Nazione
, senza specificare il contesto o il programma in cui tale classe dovrà avere un ruolo. È per questo che ci risulta difficile creare dei metodi, visto che attualmente ignoriamo il programma in cuiNazione
sarà utilizzato. Potremmo utilizzare questa classe in un programma che conserva i dati fisici delle nazioni, ma potremmo anche utilizzarlo in un videogioco che simula il famoso gioco da tavola Risiko. I metodi (ma anche le variabili d’istanza) da definire, potrebbero cambiare drasticamente da contesto a contesto. Nel primo caso infatti definiremmo variabili d’istanza comefiumi
,laghi
,montagne
,superficie
etc., e metodi comeproduce
,esporta
,importa
. Nel secondo caso invece potremmo definire iconfini
, e il metododifendi
.
Concludendo, abbiamo reso estremamente generica la definizione della classeNazione
, proprio perché non avevamo vincoli da poter sfruttare. -
Esercizio 2.n)
Data la seguente classe:
public class Esercizio2N { public String string; public int intero; final public String integer = "inzializzazione"; }
Quale delle seguenti affermazioni è vera (scegliere una sola affermazione)?1. Il codice può essere compilato correttamente.
2. Il codice non può essere compilato correttamente perché non è possibile dichiarare una variabile con nomestring
.
3. Il codice non può essere compilato correttamente perché non è possibile dichiarare una variabile con nomeintero
.
4. Il codice non può essere compilato correttamente perché non è possibile dichiarare una variabile di tipoString
chiamandolainteger
.
5. Il codice non può essere compilato correttamente perché la variabile con nomeinteger
dichiara i modificatori in ordine inverso (dovrebbe essere prima dichiaratapublic
e poifinal
).
Soluzione
La soluzione è la risposta numero 1, ovvero il codice può essere compilato senza errori. Non ci si faccia trarre in inganno dai nomi delle variabili (vedi altre possibili risposte) che potrebbero portare (volontariamente) a fare confusione. Inoltre non è un problema l’ordine in cui sono specificati i modificatori.
-
Esercizio 2.o)
Data la seguente classe:
public class Esercizio2O { public String toString() { return "Esercizio2O" } public void main() { } public static void metodo() { } static public void main(String argomenti[]) { } }
C’è un solo errore in questa classe che ne impedirà la compilazione, quale?Se non si è in grado di rispondere alla domanda, scrivere e compilare la classe a mano, e interpretare l’errore. Poi risolverlo e verificare la risoluzione compilando.
Soluzione
L’errore è che manca il
;
accanto allo statement del metodotoString
:
return "Esercizio2O"
che dovrebbe essere corretto così:
return "Esercizio2O";
Gli altri metodi sono tutti corretti. -
Esercizio 2.p)
Data la seguente classe:
public class Esercizio2P { public String stringa; public static void main(String argz[]) { public int intero = 0; } }
C’è un solo errore in questa classe che ne impedirà la compilazione, quale?Se non si è in grado di rispondere alla domanda, scrivere e compilare la classe a mano, e interpretare l’errore. Poi risolverlo e verificare la risoluzione compilando.
Soluzione
L’errore è che non si può dichiarare
public
una variabile locale all’interno di un metodo. Infattipublic
definisce la visibilità al di fuori della classe di una variabile d’istanza, non al di fuori di un metodo.
Abbiamo definitoargz
il parametro delmain
, in luogo dello standardargs
. Ciò è legale perché si tratta solo del nome di un parametro. -
Esercizio 2.q)
Data la seguente classe:
public class Esercizio2Q { public static void main(String args) { System.out.println("Quelo") } } }
Ci sono ben tre errori che in questa classe ne impediranno la compilazione, quali sono?Se non si è in grado di rispondere alla domanda, scrivere e compilare la classe a mano, e interpretare l’errore. Poi risolvere gli errori e verificare la risoluzione compilando.
Soluzione
Il primo errore è che mancano le parentesi quadre per il parametro
args
delmain
. Il secondo è perché manca il;
accanto all’unico statement del metodomain
. Il terzo è dovuto da una parentesi graffa di chiusura in più. Corretti questi errori, la classe compila e può anche essere eseguita visto che contiene un metodomain
. La classe corretta sarà la seguente:
public class Esercizio2Q_OK { public static void main(String args[]) { System.out.println("Quelo"); } }
-
Esercizio 2.r)
Data la seguente classe:
public class Esercizio2R { public int var1; public int var2; System.out.println("Esercizio 2.r"); public Esercizio2R() { } public Esercizio2R(int a , int b) { var1 = b; var2 = a; } public static void main(String args[]) { Esercizio2R esercizio2R = new Esercizio2R (4,7); System.out.println(esercizio2R.var1); System.out.println(esercizio2R.var2); } }
Una volta eseguito, cosa stamperà questo programma?
1. Questo programma non può essere eseguito.
2. Questo programma non compila.
3. Stamperà 74.
4. Stamperà 47.
Soluzione
Il programma non compilerà per via dello statement:
System.out.println("Esercizio 2.r");
che non appartiene a nessun blocco di codice di metodo. Ma abbiamo visto che all’interno di una classe sono definiti solo variabili e metodi, non statement. Eliminando quello statement, il programma:
public class Esercizio2R_OK { public int var1; public int var2; public Esercizio2R_OK() { } public Esercizio2R_OK(int a , int b) { var1 = b; var2 = a; } public static void main(String args[]) { Esercizio2R_OK esercizio2R = new Esercizio2R_OK(4,7); System.out.println(esercizio2R.var1); System.out.println(esercizio2R.var2); } }
compilerà e stamperà al runtime:
7 4
-
Esercizio 2.s)
Date le seguenti classi:
public class Corso { public String nome; public Corso() { } public Corso(String n) { nome = n; } } public class Esercizio2s { public static void main(String args[]) { Corso corso1 = new Corso(); corso1.nome = "Java"; Corso corso2 = new Corso("Java"); System.out.println(corso1.nome); System.out.println(corso2.nome); } }
Quale sequenza di istruzioni tra le seguenti serve per eseguire il programma?
1. javac Corso.java, javac Esercizio2S.java, java Corso.
2. javac Corso.java, javac Esercizio2S.java, java Corso.class.
3. javac Corso.java, javac Esercizio2S.java, java Esercizio2S.
4. javac Corso.java, javac Esercizio2S.java, java Esercizio2S Corso.
Soluzione
La risposta corretta è la 3. Sarebbe possibile anche compilare solo la classe
Esercizio2S
, visto che utilizzando la classeCorso
, essa obbligherà il compilatore a compilare anche quest’ultima. Quindi possiamo anche eseguire questa sequenza:
javac Esercizio2S.java java Esercizio2S
-
Esercizio 2.t)
Date le seguenti classi:
public class Corso { public String nome; public Corso() { } public Corso(String n) { nome = n; } } public class Esercizio2t { public static void main(String args[]) { Corso corso1 = new Corso(); corso1.nome = "Java"; Corso corso2 = new Corso("Java"); System.out.println(corso1.nome); System.out.println(corso2.nome); } }
Una volta eseguito, cosa stamperà questo programma?
1. Questo programma non può essere eseguito.
2. Questo programma non compila.
3. Stamperà:
Java Java
Java
Soluzione
La risposta corretta è la 3.
-
Esercizio 2.u)
Data la seguente classe:
public class Esercizio2u { int c = 3; public static void main(String args[]) { int a = 1; int b = 2, c, d = 4; System.out.println(a+b+c+d); } }
Una volta eseguito, cosa stamperà questo programma?
1. Questo programma non compila.
2. Stamperà "10".
3. Stamperà: "7".
4. Stamperà: "0".
Soluzione
La risposta corretta è la 1. Infatti la variabile locale
c
non è stata inizializzata e provocherà quest’errore:
Esercizio2U.java:6: error: variable c might not have been initialized System.out.println(a+b+c+d); ^ 1 error
Come asserito in questo capitolo, la variabile d’istanza omonima non c’entra nulla con la variabile locale. In qualsiasi caso, una volta inizializzata a3
:
public class Esercizio2u_OK { int c = 3; public static void main(String args[]) { int a = 1; int b = 2, c = 3, d = 4; System.out.println(a+b+c+d); } }
stamperà:
10
-
Esercizio 2.v)
Si crei una classe di nome
Esercizio2V
che consenta di ottenere la somma 2, 3, 5 e 10 numeri interi.
Soluzione
Il listato per la classe
Esercizio2V
potrebbe essere il seguente:
public class Esercizio2V { public int somma2Int(int a, int b) { return a+b; } public int somma5Int(int a, int b, int c, int d, int e) { return a+b+c+d+e; } public int somma10Int(int a, int b, int c, int d, int e, int f, int g, int h, int i, int l) { return a+b+c+d+e+f+g+h+i+l; } //Giusto per testare public static void main(String args[]) { Esercizio2V es = new Esercizio2V(); System.out.println(es.somma2Int(1,1)); System.out.println(es.somma5Int(1,1,1,1,1)); System.out.println(es.somma10Int(1,1,1,1,1,1,1,1,1,1)); } }
-
Esercizio 2.w)
Consideriamo la soluzione dell’esercizio 1.x, dove avevamo creato una classe che simulava la stampa dei dettagli di alcuni contatti di una rubrica:
public class StampaContatti { public static void main(String args[]) { System.out.println("Elenco Contatti"); System.out.println(); System.out.println("Claudio De Sio Cesari"); System.out.println("Via Java 13"); System.out.println("131313131313"); System.out.println(); System.out.println("Stevie Wonder"); System.out.println("Via Musica 10"); System.out.println("1010101010"); System.out.println(); System.out.println("Gennaro Capuozzo"); System.out.println("Piazza Quattro Giornate 1"); System.out.println("1111111111"); } }
Astrarre, salvare, e compilare una classeContatto
che contiene le necessarie variabili e uno o più costruttori.
Soluzione
Il codice della classe
Contatto
potrebbe essere il seguente:
public class Contatto { public String nome; public String indirizzo; public String numeroDiTelefono; public Contatto (String nom, String num){ nome = nom; numeroDiTelefono = num; } public Contatto (String nom, String ind, String num){ nome = nom; indirizzo = ind; numeroDiTelefono = num; } }
Notare che abbiamo deciso di definire due costruttori, uno che prende in input i valori delle tre variabili, a l’altro che fa a meno dell’indirizzo. Non abbiamo introdotto altri costruttori visto che reputiamo inutile che un contatto sia creato senza specificare almeno un nome e il numero di telefono. -
Esercizio 2.x)
Consideriamo la soluzione dell’esercizio 2.w, creiamo una nuova versione della classe
StampaContatti
dell’esercizio 1.x (il cui listato è riportato anche nella traccia dell’esercizio 2.w), questa volta sfruttando la classeContatto
creata nell’esercizio 2.w. l’output del programma deve essere lo stesso del programmaStampaContatti
dell’esercizio 1.x.Consiglio: utilizzare un metodo simile astampaDettagli
che abbiamo definito nella soluzione dell’esercizio 2.k.
Soluzione
Il codice della classe
StampaContatti
potrebbe essere il seguente:
public class StampaContatti { public static void main(String args[]) { System.out.println("Elenco Contatti"); System.out.println(); Contatto contatto1 = new Contatto("Claudio De Sio Cesari", "Via Java 13", "131313131313"); Contatto contatto2 = new Contatto("Stevie Wonder", "Via Musica 10", "1010101010"); Contatto contatto3 = new Contatto("Gennaro Capuozzo", "Piazza Quattro Giornate 1", "1111111111"); System.out.println(contatto1.nome); System.out.println(contatto1.indirizzo); System.out.println(contatto1.numeroDiTelefono); System.out.println(); System.out.println(contatto2.nome); System.out.println(contatto2.indirizzo); System.out.println(contatto2.numeroDiTelefono); System.out.println(); System.out.println(contatto3.nome); System.out.println(contatto3.indirizzo); System.out.println(contatto3.numeroDiTelefono); } }
Il codice però risulta piuttosto verboso.
Come consigliato, aggiungiamo il metodostampaDettagli
nella classeContatto
:
public class Contatto { public String nome; public String indirizzo; public String numeroDiTelefono; public Contatto (String nom, String num) { nome = nom; numeroDiTelefono = num; } public Contatto (String nom, String ind, String num) { nome = nom; indirizzo = ind; numeroDiTelefono = num; } //usato dalla versione 2 public void stampaDettagli() { System.out.println(nome); System.out.println(indirizzo); System.out.println(numeroDiTelefono); System.out.println(); } }
Possiamo riscrivere la classeStampaContatti
più semplicemente:
public class StampaContatti { public static void main(String args[]) { System.out.println("Elenco Contatti"); System.out.println(); Contatto contatto1 = new Contatto("Claudio De Sio Cesari", "Via Java 13", "131313131313"); Contatto contatto2 = new Contatto("Stevie Wonder", "Via Musica 10", "1010101010"); Contatto contatto3 = new Contatto("Gennaro Capuozzo", "Piazza Quattro Giornate 1", "1111111111"); contatto1.stampaDettagli(); contatto2.stampaDettagli(); contatto3.stampaDettagli(); } }
-
Esercizio 2.y)
Considerando la soluzione dell’esercizio 2.x, creare una classe
Rubrica
, che contenga i contatti creati nell’esercizio 2.x. Essa deve definire un costruttore senza parametri che istanzi le proprie variabili di istanza. Creare una nuova versione della classeStampaContatti
, che abbia sempre lo stesso output. Tale versione non deve istanziare gli oggettiContatto
, ma prenderli dalla classeRubrica
.
Soluzione
Il codice della classe
Rubrica
potrebbe essere il seguente:
public class Rubrica { public Contatto contatto1; public Contatto contatto2; public Contatto contatto3; public Rubrica () { contatto1 = new Contatto("Claudio De Sio Cesari", "Via Java 13", "131313131313"); contatto2 = new Contatto("Stevie Wonder", "Via Musica 10", "1010101010"); contatto3 = new Contatto("Gennaro Capuozzo", "Piazza Quattro Giornate 1", "1111111111"); } }
Di conseguenza la classeStampaContatti
potrà essere modificata nel seguente modo:
public class StampaContatti { public static void main(String args[]) { System.out.println("Elenco Contatti"); System.out.println(); Rubrica rubrica = new Rubrica(); rubrica.contatto1.stampaDettagli(); rubrica.contatto2.stampaDettagli(); rubrica.contatto3.stampaDettagli(); } }
-
Esercizio 2.z)
Creare una classe che astragga il concetto di "città", chiamandola
Citta
(Java non supporta le lettere accentate per i nomi). Dopodiché dichiarare una classeNazione
che dichiari una variabile d’istanzacapitale
di tipoCitta
. Infine creare una classeEsercizio2Z
che istanzi unaNazione
con una capitale, e stampi una frase che verifichi l’effettiva associazione tra la nazione e la capitale.Si consiglia di creare dei costruttori per tali classi.
Soluzione
Una soluzione potrebbe essere costituita dalla codifica delle seguenti classi:
public class Citta { public String nome; public Citta (String n) { nome = n; } } public class Nazione { public String nome; public Citta capitale; public int popolazione; public Nazione (String n, Citta c, int p) { nome = n; capitale = c; popolazione = p; } } public class Esercizio2z { public static void main(String args[]) { Citta capitale = new Citta("Roma"); Nazione italia = new Nazione("Italia", capitale, 60_000_000); System.out.println("L'" + italia.nome + " ha come capitale " + italia.capitale.nome); } }
-
Esercizio 2.aa)
Creare una classe
Libro
, che definisce le variabili che si ritiene opportuno, un costruttore che ci permetta di inizializzarle, ed un metodostampaDettagli
, sul modello del metodo definito nella classeContatto
dell’esercizio 2.y. Creare anche una classeTestLibro
che testa il funzionamento della classeLibro
, che istanzia due libri e chiami il metodostampaDettagli
per ognuno di loro. Controllare se la stampa ottenuta è quella desiderata.
Soluzione
Una soluzione potrebbe essere costituita dalle seguenti classi. Iniziamo dalla classe
Libro
:
public class Libro { public String titolo; public String autore; public String editore; public Libro (String t, String a, String e) { titolo = t; autore = a; editore = e; } public void stampaDettagli() { System.out.println(titolo); System.out.println(autore); System.out.println(editore); System.out.println(); } }
Nonostante il codice sia abbastanza leggibile ed interpretabile, facciamo prima qualche osservazione sulla classeLibro
, per non avere dubbi su quello che abbiamo scritto.
Questa classe definisce tre variabili chiamatetitolo
,autore
eeditore
. Tali variabili sono definite usando il modificatorepublic
, che come vedremo ci permetterà di utilizzarle anche in altre classi. Le variabili sono dichiarate di tipoString
, ovvero possiamo assegnare a queste variabili delle stringhe, ovvero sequenze di caratteri comprese tra virgolette (abbiamo già visto diverse stringhe nei programmi fatti nel capitolo 1).
Queste rappresentano per noi le caratteristiche essenziali per astrarre una classeLibro
. Potevamo dichiarare anche la variabilesottotitolo
,numeroPagine
,prezzo
e così via, ma quando si decide di creare una classe, si deve astrarla con le caratteristiche necessarie alla situazione. Siccome la nostra necessità è solo quella di fare un esempio, non abbiamo ritenuto utile aggiungere altre caratteristiche.
Come si può notare, le variabili della classe non hanno dei valori, perché non stiamo definendo un particolare libro. Con il seguente codice creiamo quindi oggetti di tipoLibro
:
public class TestLibro { public static void main(String args[]) { Libro nuovoJava = new Libro("Il nuovo Java", "Claudio De Sio Cesari", "Hoepli"); nuovoJava.stampaDettagli(); Libro giornoDellaCivetta = new Libro("Il giorno della civetta", "Leonardo Sciascia", "Adelphi"); giornoDellaCivetta.stampaDettagli(); } }
-
Esercizio 2.bb)
Creare una classe
CalcolaPerimetroQuadrato
, che calcola il perimetro di un quadrato che abbia come lunghezza del lato il valore17
, e ne stampi il risultato. Usare questa volta solo una classe con metodomain
, che dichiari delle variabili in maniera leggibile.È possibile anche settare il valore del lato tramite un oggettoScanner
come fatto negli esempi del capitolo 1.
Soluzione
La classe richiesta potrebbe essere implementata nel seguente modo:
public class CalcolaPerimetroQuadrato { public static void main(String args[]) { int lunghezzaLatoQuadrato = 17; int numeroLati = 4; int perimetroQuadrato = lunghezzaLatoQuadrato * numeroLati; System.out.println("Il perimetro del quadrato è:"); System.out.println(perimetroQuadrato); } }
L’output sarà:
Il perimetro del quadrato è: 68
Questa classe calcola il perimetro di un quadrato facendo uso di tre variabili di tipo int. In particolare, possiamo notare come alla variabileperimetroQuadrato
venga assegnato il valore calcolato dalla moltiplicazione del valore della variabilelunghezzaLatoQuadrato
e il valore della variabilenumeroLati
. Notare che le variabili hanno aggiunto leggibilità al codice. Infatti, avremmo potuto ottenere lo stesso risultato e il medesimo output con il seguente codice che non fa uso di variabili:
public class CalcolaPerimetroQuadratoSenzaVariabili { public static void main(String args[]) { System.out.println("Il perimetro del quadrato è:"); System.out.println(17 * 4); } }
Ma probabilmente avremmo avuto qualche dubbio in più rispetto alla comprensione del codice. Scegliere un identificatore per una variabile, potrebbe sembrare una banalità, ma non lo è, e non deve mai esserlo! Per esempio, potremmo riscrivere la classeCalcolaPerimetroQuadrato
senza impegnarci a trovare dei nomi significativi per le variabili nel seguente modo:
public class CalcolaPerimetroQuadratoABC { public static void main(String args[]) { int a = 17; int b = 4; int c = a * b; System.out.println("Il perimetro del quadrato è:"); System.out.println(c); } }
Non è più difficile da leggere? Inoltre, scrivere un programma, significa ritornare a leggere e modificare continuamente il codice affinché esso funzioni. Non sempre il codice funziona al primo tentativo, ed inoltre il software ha bisogno di evolversi in futuro, aggiungendo nuove funzionalità e modificando quelle esistenti. Una variabile con un identificatore adatto, non solo ci permetterà di leggere più facilmente il vostro codice anche dopo tanto tempo, ma a volte ci indirizzerà verso la soluzione più corretta. -
Esercizio 2.cc)
Consideriamo la classe
Aritmetica
definita nel paragrafo 2.2.2.3:
public class Aritmetica { public int somma(int a, int b) { return (a + b); } }
Creare una versione "maggiormente leggibile" di questa classe, così come spiegato nel paragrafo 2.2.2.3.
Soluzione
Notiamo che il nome del metodo (
somma
) non descrive completamente la funzionalità che vuole definire. L’identificatoresommaDueInteri
, sarebbe più "parlante", e non lascerebbe dubbi sulla implementazione del metodo. Tutto sommato però, anche il nome somma sembra accettabile. Infatti, questo metodo dichiara come lista di parametri due variabili di tipoint
, e i parametri di un metodo rappresentano l’input del metodo. Quando questo metodo verrà chiamato, bisognerà passargli in input due valori di tipo intero. Non potremo passare a questo metodo valori non interi come26.1
, oppureabc
. L’identificatoresomma
quindi, può essere considerato un buon identificatore, perché non ci sono dubbi sul fatto che il metodo possa fare la somma solamente di due numeri interi. D’altronde, "un metodo è determinato dalla coppia costituita dall’identificatore e l’eventuale lista dei parametri" (firma del metodo).
Come nome dei parametri abbiamo sceltoa
eb
. Sebbene, siano identificatori coincisi, che ci permettono di risparmiare qualche digitazione, rimangono nomi che non astraggono bene i concetti che vogliono rappresentare. Ne comprendiamo l’utilità, solo perché stiamo definendo un metodo molto semplice e conosciamo bene cosa sia una addizione. Tuttavia, non sarà sempre così. Scegliere identificatori "parlanti", è fondamentali per la leggibilità del nostro codice, e quindi per semplificare la nostra interazione con il codice stesso. Sarebbe preferibile quindi, utilizzare identificatori comeaddendo1
eaddendo2
, oppure i più genericioperando1
edoperando2
.
Per quanto riguarda il tipo di ritorno, per la prima volta non troviamo la parola chiavevoid
, maint
, che rappresenta un numero intero. Ciò significa che quando questo metodo sarà invocato, esso restituirà in output un valore di tipo intero. Infatti, nell’ultima istruzione del metodosommaDueInteri
, i due parametri saranno sommati tramite l’operatore+
, e il risultato della loro somma verrà restituita come output tramite il comandoreturn
:
return (a + b);
L’output sarà:
Il perimetro del quadrato è: 68
Il risultato che viene restituito da questo metodo è la somma di due interi, che è ovviamente un intero. Ecco perché il tipo di ritorno è dichiarato comeint
.
Nell’unico statement contenuto nel blocco di codice quindi, ci sono due istruzioni: la somma dei due parametri ed il comandoreturn
, che provoca la terminazione del metodo, ritornando il valore successivamente specificato.
Anche in questo caso, sottolineiamo che il blocco di codice del metodo, anche se tecnicamente corretto, potrebbe essere astratto in maniera diversa. Condensando tutta la logica in un unico statement, abbiamo indubbiamente sacrificato la leggibilità del codice alla sinteticità. Per un esempio così semplice questo è accettabile, ma dopo le nostre considerazioni possiamo creare una nuova versione della classeAritmetica
, usando l’astrazione per rendere il programma più leggibile:
public class AritmeticaLeggibile { public int sommaDueInteri(int addendo1, int addendo2) { int risultato = addendo1 + addendo2; return risultato; } }
-
Esercizio 2.dd)
Consideriamo la classe
Aritmetica
definita nel paragrafo 2.2.2.3:
public class Aritmetica { public int somma(int a, int b) { return (a + b); } }
Creare una versione che rappresenta un compromesso tra la versione leggibile e la versione sintetica di questa classe, così come spiegato nel paragrafo 2.2.2.3.
Soluzione
Un giusto compromesso, e questo dipende dalla nostra capacità di astrazione, la nostra pazienza, dalla nostra forma mentis, dalla nostra esperienza di programmazione ed altri fattori. Per questo esempio, potrebbe essere un compromesso accettabile la seguente implementazione:
public class AritmeticaCompromesso { public int somma(int addendo1, int addendo2) { return addendo1 + addendo2; } }
Tuttavia, essendo un parere soggettivo potreste scegliere di implementare la classe in maniera diversa.