Il corso offre una selezione di argomenti di programmazione avanzata, con particolare riferimento al paradigma ad oggetti e al linguaggio Java.
Sono trattati sia temi specificamente legati al linguaggio Java, come i dettagli del binding dinamico, sia temi di natura progettuale, come i design pattern.
Tra questi due estremi, vengono affrontati numerosi problemi di progettazione e implementazione comuni ai moderni linguaggi orientati agli oggetti, come il confronto e l’ordinamento tra oggetti, la programmazione con parametri di tipo e la creazione di programmi multi-thread.
Gli argomenti sono trattati con un taglio orientato alla pratica, allo scopo di preparare gli studenti alla progettazione e realizzazione di sistemi software complessi.
Questo corso presuppone una conoscenza base del linguaggio Java, in quanto il linguaggio di riferimento è Java 1.5, ma è anche possibile utilizzare ambienti di sviluppo, compilatori e libri di testo riferiti a versioni successive del linguaggio.
Questo corso presuppone la conoscenza dei seguenti argomenti di Java elementare:
I tipi base sono otto: void, boolean, char, byte, short, int, float double.
Tra tipi base esistono le seguenti conversioni implicite (o promozioni):
Le conversioni implicite sono transitive.
Se esiste una conversione implicita dal tipo x al tipo y, è possibile assegnare un valore di tipo x ad una variabile di tipo y.
Alcune di queste conversioni possono comportare una perdita di informazione. Ad esempio:
Inserire una dichiarazione (e inizializzazione) per la variabile i, in modo che il seguente ciclo sia infinito.
while (i == i+1) {...}
Quante volte viene eseguito il seguente ciclo?
for (double x=0; x!=1 ;x++) {...}
A differenza di altri linguaggi orientati agli oggetti (ad es., il C++), non esistono variabili che contengono oggetti, solo riferimenti ad oggetti, ovvero variabili che contengono l’indirizzo di un oggetto.
Tali riferimenti Java sono quindi simili ai puntatori del linguaggio C.
Tuttavia, i riferimenti Java sono molto più restrittivi:
Quindi, rispetto ai puntatori, i riferimenti Java sono meno potenti, più facili da utilizzare e meno soggetti ad errori al run-time.
Java prevede solo il passaggio per valore: sia i tipi base che i riferimenti sono passati per valore
Non è possibile passare oggetti per valore, l’unico modo di manipolare (ed in particolare, passare) oggetti è tramite i loro riferimenti (ovvero, indirizzi).
Si utilizzerà talvolta la nozione di “memory layout” di un programma.
Ci si riferisce ad una rappresentazione grafica dello stato della memoria ad un determinato punto di un programma.
Come primo esempio, dato il frammento di codice Java:
il suo memory layout può essere raffigurato come in figura 1.
Solitamente, i diagrammi di memory layout di queste slide non evidenziano la differenza tra allocazione su stack e su heap.
In Java, gli array sono oggetti a tutti gli effetti.
In particolare, sono sottotipi di Object e ne ereditano i metodi.
Non esistono variabili che contengono (direttamente) array, ma solo riferimenti ad array.
Ad esempio, in figura viene riportato il memory layout del seguente frammento di programma:
int[] a = new int[5];
int[] b = a;
int[][] c = new int[3][];
c[1] = b;
c[2] = new int[7];
1) Inserire una dichiarazione (e inizializzazione) per la variabile i, in modo che il seguente ciclo sia infinito.
while (i == i+1) {...}
Soluzione: float i = 1000000000;
Sommare 1 ad i non ne modifica il valore, in quanto, come illustrato precedentemente, un float non ha abbastanza cifre binarie nella mantissa per rappresentare il numero “un miliardo e uno”.
2) Quante volte viene eseguito il seguente ciclo?
for (double x=0; x!=1 ;x+=0.1) {...}
Soluzione: infinite volte.
La variabile x non assumerà mai esattamente il valore 1, perché 0.1 non è rappresentabile in maniera esatta con un double. Infatti, in rappresentazione binaria 0.1 è il numero periodico 0.00011.
La morale di questi esercizi è che l’aritmetica in virgola mobile nasconde molte insidie. A tale proposito, si veda anche l’interessante disamina “How Java’s Floating-Point Hurts Everyone Everywhere”, facilmente rintracciabile sul web.
4. Risoluzione dell'overloading e dell'overriding
5. Controllo di uguaglianza tra oggetti
6. Classi interne, locali ed anonime
7. Iteratori, teoria e pratica
8. Clonazione di oggetti. Confronto tra oggetti.
9. Elementi di programmazione di interfacce grafiche
10. Il paradigma Model-View-Controller. Il pattern Strategy
11. I pattern Composite e Decorator
12. I pattern Template Method e Factory Method
13. Classi e metodi parametrici
14. La libreria Java Collection Framework: le interfacce Iterable, ...
15. La libreria Java Collection Framework: la classe HashSet e le l...
16. Parametri di tipo con limiti
17. L'implementazione della programmazione generica: la cancellazio...
18. La riflessione
19. Introduzione al multi-threading
22. Classi enumerate
C.S. Horstmann, Progettazione del software e design pattern in Java, Apogeo.
C.S. Horstmann e Cornell, Core Java 2, (7° edizione), volumi 1 e 2, Pearson/Prentice Hall.
Per approfondimenti:
M. Gabbrielli e S. Martini, Linguaggi di programmazione, principi e paradigmi, McGraw-Hill, cap. 10 in particolare.