Docsity
Docsity

Prepara i tuoi esami
Prepara i tuoi esami

Studia grazie alle numerose risorse presenti su Docsity


Ottieni i punti per scaricare
Ottieni i punti per scaricare

Guadagna punti aiutando altri studenti oppure acquistali con un piano Premium


Guide e consigli
Guide e consigli


JAVA - Programmazione Orientata agli Oggetti (OOP), Sintesi del corso di Programmazione Orientata agli Oggetti

Concetti di progettazione del software Concetti di programmazione OOP Java JCF Swing

Tipologia: Sintesi del corso

2019/2020

Caricato il 16/10/2020

walker-alonso-diaz-cama
walker-alonso-diaz-cama 🇮🇹

5

(1)

1 documento

1 / 42

Toggle sidebar

Questa pagina non è visibile nell’anteprima

Non perderti parti importanti!

bg1
16/10/2020 codeprinter
https://jaredpetersen.github.io/codeprinter/ 1/42
______________________________________________________________________________
CONCETTI BASE DELLA PROGETTAZIONE DEL SOFTWARE
______________________________________________________________________________
_ Introduzione alla progettazione del software
– Contesto organizzativo
– Ciclo di vita del software
– Qualità
– Modularizzazione
– Principi di base dell’orientazione agli oggetti
_ Classificazione delle applicazioni
Rispetto al flusso di controllo
• Sequenziali: un unico flusso di controllo governa l’evoluzione dell'applicazione
• Concorrenti: le varie attività necessitano di sincronizzazione e comunicazione
• Composte da varie attività sequenziali che possono (e devono) essere sincronizzate
al fine di garantire la correttezza
• Il tempo di esecuzione influenza le prestazioni, non la correttezza
• Dipendenti dal tempo: esistono vincoli temporali riguardanti sia la velocità di
esecuzione delle attività sia la necessità di sincronizzare le attività stesse
Rispetto agli elementi di interesse primario
• Orientate alla realizzazione di funzioni: la complessità prevalente del sistema
riguarda le funzioni da realizzare
• Orientate alla gestione dei dati: l’aspetto prevalente è rappresentato dai dati che
vengono memorizzati, ricercati, e modificati, e che costituiscono il patrimonio
informativo di una organizzazione
• Orientate al controllo: la complessità prevalente del sistema riguarda il controllo
delle attività che si sincronizzano e cooperano durante l'evoluzione del sistema
_ Ciclo di vita del software
1. Studio di fattibilità e raccolta dei requisiti
– valutare costi e benefici
– pianificare le attività e le risorse del progetto
– individuare l'ambiente di programmazione (hardware/software)
– raccogliere i requisiti
2. Analisi dei requisiti
– si occupa del cosa l’applicazione dovrà realizzare
– descrivere il dominio dell’applicazione e specificare le funzioni delle varie
componenti: lo
schema concettuale
3. Progetto e realizzazione
– si occupa del come l’applicazione dovrà realizzare le sue funzioni
– definire l'architettura del programma
– scegliere le strutture di rappresentazione
– scrivere il codice del programma e produrre la documentazione
4. Verifica
– Il programma svolge correttamente, completamente, efficientemente il
compito per cui è stato sviluppato?
5. Manutenzione
– Controllo del programma durante l'esercizio
– Correzione e aggiornamento del programma
_ Fattori di qualità del SW
ESTERNE
Correttezza
Affidabilità
Robustezza
Sicurezza
Innocuità
Usabilità
Estendibilità
Riusabilità
Interoperabilità
pf3
pf4
pf5
pf8
pf9
pfa
pfd
pfe
pff
pf12
pf13
pf14
pf15
pf16
pf17
pf18
pf19
pf1a
pf1b
pf1c
pf1d
pf1e
pf1f
pf20
pf21
pf22
pf23
pf24
pf25
pf26
pf27
pf28
pf29
pf2a

Anteprima parziale del testo

Scarica JAVA - Programmazione Orientata agli Oggetti (OOP) e più Sintesi del corso in PDF di Programmazione Orientata agli Oggetti solo su Docsity!

______________________________________________________________________________

CONCETTI BASE DELLA PROGETTAZIONE DEL SOFTWARE

______________________________________________________________________________

_ Introduzione alla progettazione del software

  • Contesto organizzativo
  • Ciclo di vita del software
  • Qualità
  • Modularizzazione
  • Principi di base dell’orientazione agli oggetti

_ Classificazione delle applicazioni Rispetto al flusso di controllo

  • Sequenziali: un unico flusso di controllo governa l’evoluzione dell'applicazione
  • Concorrenti: le varie attività necessitano di sincronizzazione e comunicazione
  • Composte da varie attività sequenziali che possono (e devono) essere sincronizzate al fine di garantire la correttezza
  • Il tempo di esecuzione influenza le prestazioni, non la correttezza
  • Dipendenti dal tempo: esistono vincoli temporali riguardanti sia la velocità di esecuzione delle attività sia la necessità di sincronizzare le attività stesse Rispetto agli elementi di interesse primario
  • Orientate alla realizzazione di funzioni: la complessità prevalente del sistema riguarda le funzioni da realizzare
  • Orientate alla gestione dei dati: l’aspetto prevalente è rappresentato dai dati che vengono memorizzati, ricercati, e modificati, e che costituiscono il patrimonio informativo di una organizzazione
  • Orientate al controllo: la complessità prevalente del sistema riguarda il controllo delle attività che si sincronizzano e cooperano durante l'evoluzione del sistema

_ Ciclo di vita del software

  1. Studio di fattibilità e raccolta dei requisiti
    • valutare costi e benefici
    • pianificare le attività e le risorse del progetto
    • individuare l'ambiente di programmazione (hardware/software)
    • raccogliere i requisiti
  2. Analisi dei requisiti
    • si occupa del cosa l’applicazione dovrà realizzare
    • descrivere il dominio dell’applicazione e specificare le funzioni delle varie componenti: lo schema concettuale
  3. Progetto e realizzazione
    • si occupa del come l’applicazione dovrà realizzare le sue funzioni
    • definire l'architettura del programma
    • scegliere le strutture di rappresentazione
    • scrivere il codice del programma e produrre la documentazione
  4. Verifica
    • Il programma svolge correttamente, completamente, efficientemente il compito per cui è stato sviluppato?
  5. Manutenzione
    • Controllo del programma durante l'esercizio
    • Correzione e aggiornamento del programma

_ Fattori di qualità del SW ESTERNE Correttezza Affidabilità Robustezza Sicurezza Innocuità Usabilità Estendibilità Riusabilità Interoperabilità

INTERNE

Efficienza Strutturazione Modularità Comprensibilità Verificabilità Manutenibilità Portabilità

_ Correttezza, Affidabilità,Robustezza, Sicurezza, Innocuità

  • Correttezza (è fondamentale) il software fa quello per il quale è stato progettato
  • Affidabilità: si può fare affidamento sulle funzionalità del software: vincoli rispettati à risultati disponibili
  • Robustezza: comportamento accettabile anche nel caso di situazioni non previste nella specifica dei requisiti
  • Innocuità: il sistema non entra in certi stati (pericolosi)
  • Sicurezza: riservatezza nell’accesso alle informazioni

_ Usabilità

  • Enfasi sull’utente
  • Psicologia cognitiva
  • Fattori fisici/ergonomici
  • Mentalità dell’utente
  • Interfacce grafiche/visuali
  • Viene, spesso, totalmente ignorata

_ Estendibilita Facilità con cui il SW può essere adattato a modifiche delle specifiche Nota: Importantissimo in grandi programmi Nota: Due principi per l'estendibilità:

  • Semplicità di progetto
  • Decentralizzazione nell'architettura del SW

_ Riusabilità Facilità con cui il SW può essere re-impiegato in applicazioni diverse da quella originaria Nota: Evita di reinventare soluzioni Nota: Richiede alta compatibilità

  • Libreria di componenti riutilizzabili
  • Progetto più generale possibile
  • Documentazione
  • Maggiore affidabilità

_ Interoperabilità

  • Facilità di interazione con altri moduli al fine di svolgere un compito più complesso
  • Problemi tecnologici e semantici
  • Favorisce la riusabilità

_ Efficienza

  • Si riferisce al “peso” che il software ha sulle risorse del sistema
    • Tempo di esecuzione
    • Utilizzo di memoria
  • Teoria della complessità à corso di Fond. Informatica II
    • limiti asintotici
    • caso medio
    • caso peggiore
  • Simulazioni (e.g., teoria delle reti di code)
  • le informazioni che non devono essere scambiate devono essere gestite privatamente dal modulo

_ Principi per la modularità In sintesi, i quattro dogmi della modularizzazione sono:

  • Alta coesione (omogeneità interna)
  • Basso accoppiamento (indipendenza da altri moduli)
  • Interfacciamento esplicito (chiare modalità d’uso)
  • Information hiding (poco rumore nella comunicazione)

_ Concetti di base dell'approccio OO

  • Oggetti
    • Descrivere i dati come oggetti sui quali si possono esegure delle operazioni.
  • Classi
    • Raggruppare oggetti simili in unità, dette «classi», dove ne viene specificata la struttura e il comportamento.
  • Astrazione
    • Il meccanismo con cui si specifica le caratteristiche peculiari di un oggetto che lo differenzia da altri
  • Ereditarietà
  • Gli oggetti sono definiti in una gerarchia di generalizzazione di classi ed ereditano dagli «antenati» caratteristiche comuni, che possono essere specializzate
  • Polimorfismo
  • Possibilità di eseguire funzioni con lo stesso nome che pure sono state specializzate per una particolare classe

_ Fattori di qualità influenzati dall'approccio OOP ESTERNE Correttezza Affidabilità Robustezza Sicurezza Innocuità Usabilità Estendibilità favorita dalla ereditarietà Riusabilità favorita dal concetto di classe e di ereditarietà Interoperabilità

INTERNE Efficienza Strutturazione favorita dal concetto di incapsulamento e dalla ereditarietà Modularità favorita dal concetto di classe Comprensibilità favorita dalla struttura vicina al modo in cui vediamo la realtà Verificabilità Manutenibilità Portabilità


JAVA OOP


_ Espressione condizionale Sintassi

(espressione booleana)?: Semantica Il risultato dell'espressione condizionale è dato dal primo valore se la condizione booleana è vera, oppure dal secondo valore se la condizione è falsa. Esempio int x,y; …. // x e y diversi System.out.println((x<y?x:y)+" è minore di "+(x>y?x:y));

_ Classi associate ai tipi primitivi Per ogni tipo primitivo esiste la corrispondente classe associata (denominata classe wrapper) byte short int long float double char boolean Byte Short Integer Long Float Double Character Boolean

_ Conversione STRING to INT String s = JOptionPane.showInputDialog("Inserisci un numero"); int x = Integer.parseInt(s);

_ Generare numero random int x =(int) (Math.random () * 6 + 1); // numero intero tra 1 e 6

_ Overloading di metodi

  • L’overloading di metodi è presente quando si usano gli stessi nomi per indicare metodi diversi
  • La segnatura di ciascun metodo coinvolto dal processo di overloading deve essere unica
  • La segnatura include il numero, tipo e l’ordine dei parametri
  • Il tipo del valore di ritorno di un metodo fa parte della segnatura?
    • OOP in generale: sì
    • Java: no
  • Il compilatore determina la versione del metodo da invocare analizzando i parametri

_ Passaggio dei parametri •Tipi di dato primitivi passaggio per valore •Riferimenti ad oggetti passaggio per valore (che però è riferimento ad un oggetto su heap)

_ Variabili statiche con valori costanti tipo FINAL public static final tipo nomeVariabile=valore;

Esempio: public class Utilita { public static final int ZERO=0; ...

_ Classi non pubbliche Classi non pubbliche possono essere definite in qualsiasi file che contiene una (e una sola) classe pubblica.

_ Compilare ed eseguire un programma JAVA COMPILARE javac Primo.java

Crea il file Primo.class ESEGUIRE java Primo

_ Inizializzazioni implicite dei campi dati di una classe

  • Metodo ereditato dalla classe Throwable:
    • String getMessage() restituisce come stringa il messaggio contenuto nell’eccezione
  • Quando l’eccezione viene lanciata:
    • può essere già stata creata o venir creata contestualmente
  • Garbage collector: distrugge solo le eccezioni che sono state catturate

_ Custom Exception import java.io.*; class ClasseEcc { void ff() throws IOException { Exception ec = new Exception("Prima eccezione"); InputStreamReader isr = new InputStreamReader(System.in); BufferedReader br = new BufferedReader(isr); int i = Integer.parseInt(br.readLine()); try { if (i == 1) throw ec; throw new Exception("Altra eccezione"); } catch(Exception e) { System.out.println(e.getMessage()); } System.out.println("Prosecuzione della funzione"); } public static void main (String[] args) throws IOException { ClasseEcc ex = new ClasseEcc(); ex.ff(); System.out.println("Prosecuzione del programma"); } }

_ Lanciare eccezioni

  • Per lanciare un’eccezione, usiamo la parola chiave throw (lancia), seguita da un oggetto di tipo eccezione throw exceptionObject;
  • Il metodo termina immediatamente e passa il controllo al gestore delle eccezioni
    • Le istruzioni successive non vengono eseguite

Esempio: public class BankAccount { public void withdraw(double amount) { if (amount > balance) throw new IllegalArgumentException(“Saldo insufficiente"); balance = balance - amount; } ... }

La stringa in input al costruttore di IllegalArgumentException rappresenta il messaggio d’errore da associare all’eccezione

_ Segnalare eccezioni

  • BufferedReader.readLine() può lanciare una IOException
  • Un metodo che chiama readLine() può
    • gestire l’eccezione, cioè dire al compilatore cosa fare
    • non gestire l’eccezione, ma dichiarare di poterla lanciare
  • In tal caso, se l’eccezione viene lanciata, il programma termina visualizzando un messaggio di errore
  • Per segnalare le eccezioni controllate che il metodo può lanciare usiamo la parola chiave

throws public void read(BufferedReader in) throws IOException

Esempio: public class Coin { public void read(BufferedReader in) throws IOException { value = Double.parseDouble(in.readLine()); name =in.readLine(); } ... } La clausola throws segnala al chiamante di Coin.read che esso può generare un’eccezione di tipo IOException

_ Usare le eccezioni di Run Time

  • Le eccezioni di runtime (RuntimeException) possono essere utilizzate per segnalare problemi dovuti ad input errati.
  • Esempi:
  • Un metodo che preleva soldi da un conto corrente non può prelevare una quantità maggiore del saldo
  • Un metodo che effettua una divisione non può dividere un numero per zero

_ Custom Exception Example: Divisione per zero public class DivisionePerZeroException extends RuntimeException{ public DivisionePerZeroException() { super("Divisione per zero!"); } public DivisionePerZeroException(String msg) { super(msg); } }

public class Divisione { public Divisione(int n, int d) { num=n; den=d; } public double dividi(){ if (den==0) throw new DivisionePerZeroException(); return num/den; } private int num; private int den; }

public class Test { public static void main(String[] args) throws IOException { double res; Scanner scan = new Scanner(System.in); System.out.print("Inserisci il numeratore:"); int n= Integer.parseInt(scan.nextLine()); System.out.print("Inserisci il denominatore:"); int d= Integer.parseInt(scan.readLine()); try { Divisione div = new Divisione(n,d);

ByteArrayOutputStream FileOutputStream ObjectOutputStream PipedOutputStream FilterOutputStream BufferedOutputStream DataOutputStream PrintStream

Stream di caratteri Reader (Input di caratteri) BufferedReader CharArrayReader InputStreamReader FileReader StringReader PipedReader FilterReader Writer (Output di caratteri) BufferedWriter CharArrayWriter OutputStreamWriter FileWriter StringWriter PipedWRiter FilterWriter PrintWriter

_Example: PrintWriter video = new PrintWriter(System.out); video.println(12); video.println(“Ciao”); video.println(13,56);

_ Lettura/Scrittura file: -FileInputStream -FileOutputStream

  • Sono sottoclassi di InputStream e OutputStream
  • Aprono stream di byte da/verso file
  • Hanno gli stessi metodi di InputStream e OutputStream
  • Si possono applicare i filtri (ad esempio DataInputStream e DataOutputStream)
  • Costruttori:
    • public FileInputStream(File file) throws FileNotFoundException
    • public FileInputStream(String name) throws FileNotFoundException

-FileReader -FileWriter

  • Sono sottoclassi di Reader e Writer
  • Aprono stream di caratteri da/verso file
  • Hanno gli stessi metodi di Reader e Writer
  • Si possono applicare BufferedReader e BufferedWriter
  • Costruttori:
    • public FileReader(File file) throws FileNotFoundException
    • public FileReader(String name) throws FileNotFoundException
    • public FileWriter(File file) throws FileNotFoundException
    • public FileWriter(String name) throws FileNotFoundException
    • public FileWriter(String name, boolean append) throws FileNotFoundException

_ Livello di logging

  • descrive la gravità e l’urgenza di un messaggio
  • Alcuni livelli tipici, in ordine decrescente
    • SEVERE: problema molto grave
    • WARNING: avvertimento potenz. grave
    • INFO: messaggio informativo sul funzionam.
    • FINE: messaggio di “tracing”
    • FINEST: messaggio di “tracing” dettagliato

_ Derivazione -Tutte le proprietà definite per la classe base vengono implicitamente definite anche nella classe derivata cioè vengono ereditate da quest’ultima. -La classe derivata può avere ulteriori proprietà -Ogni oggetto della classe derivata è anche un oggetto della classe base cioè si può usare un oggetto della classe derivata in ogni situazione/contesto in cui si può usare un oggetto della classe base -Non è vero che un oggetto della classe base è anche un oggetto della classe derivata non è possibile usare un oggetto della classe base laddove si può usare un oggetto della classe derivata. -Una classe derivata può fungere da classe base per ulteriori derivazioni public class B {…} public class D extends B {…} public class E extends D {…} -Una classe può avere un numero qualsiasi di classi derivate public class B {…} public class D extends B {…} public class Dbis extends B {…} -Riferimenti di diverse classi possono denotare lo stesso oggetto WRONG: public class B {…} public class D extends B { int x_d; } … D d = new D(); d.x_d = 10; B b = d; //OK b e d denotano lo stesso ogg. b.x_d = 20; //NO x_d non è un campo di B! //type checking statico CORRECT: public class B {…} public class D extends B { int x_d; } … D d = new D(); d.x_d = 10; B b = d; //OK b e d denotano lo stesso ogg. ((D)b).x_d = 20; //OK (D)b è un riferimento di tipo D

_ this() -da utilizzare in modo analogo a super() -è un’invocazione esplicita ad un altro costruttore della stessa classe -permette si riusare codice già scritto

Example: //File Persona.java public class Persona {

//campi dati (variabili di istanza) private String nome; private String residenza;

//costruttori public Persona() {

Definizione: è una astrazione per un insieme di funzioni pubbliche, delle quali si definisce la segnatura ma non il corpo.

-Una classe implementa l’interfaccia definendo TUTTE le funzioni previste dalla stessa.

_ Summary interface Una interfaccia è simile ad una classe dove non possono essere presenti campi dati (eccetto costanti statiche…). Inoltre tutte le funzioni sono astratte (segnatura, ma non corpo). Le interfacce rappresentano collezioni di funzionalità messe a disposizione dalle classi che le implementano

_ Differenza tra interface e classi abstract -una classe astratta è una classe, cioè una astrazione di un insieme di oggetti simili (quelli delle sue sottoclassi) -una interfaccia è una semplice astrazione di un insieme di funzionalità

_ Altro su interfacce -Una classe può implementare un'interfaccia public interface I { void g(); } public interface J { void h(); }

public class C implements I,J { void g(){…} void h(){…} }

-Una interfaccia può essere derivata da un’altra interfaccia public interface I { void g(); } public interface J extends I {void h();}

public class C implements J { void g(){…} void h(){…} }

-Java supporta ereditarietà multipla per le interfacce (non per le classi) public interface I {void g();} public interface J {void h();} public interface M extends I,J {void k();}

public class C implements M { void g(){…} void h(){…} void k(){…} }

_ Classe Object -Tutte le classi Java sono implicitamente derivate da Object -Tutti gli oggetti, qualunque sia la classe a cui appartengono, sono istanze di Object e ne ereditano le funzioni

_ Funzioni di Object -public String toString(); -Associa all’oggetto di invocazione una stringa stampabile, se ne può fare l'overriding -toString() e derivazione: -nel farne overriding possiamo riusare toString() della classe base -Example: //EsempioToStringDerivata public class B { private int i;

public B(int x) { i = x; } public String toString() { return "i: " + i; } }

public class D extends B { private int j; public D(int x, int y) { super(x); j = y; } public String toString() { return super.toString() + " j: " + j; } }

public class EsempioToStringDerivata { public static void main(String[] args) { D d = new D(5,10); System.out.println(d); } } /* Stampa: i: 5 j: 10 */

-public Final Class getClass(); -public boolean equals(Object o); -protected Object clone(); -public int hashCode(); -etc...

_ La classe Class -Nella JVM esiste implicitamente un oggetto della classe Class per ogni classe (o interfaccia) del programma. C.class Class: Class c = … -Class non ha costruttori accessibili ai clienti

_ La funzione isInstance boolean isInstance (Object o)

_La funzione restituisce true se o denota un oggetto che è istanza della classe (interfaccia) rappresentata dall’oggetto di invocazione. Si usa per verificare se un oggetto è istanza di una classe.

_Example: //EsempioIsInstance

public class B {}

public class D extends B {}

public class EsempioIsIntance1 { public static void main(String[] args) { B b1 = new B(); D d1 = new D(); System.out.println(B.class.isInstance(b1)); //"true" System.out.println(B.class.isInstance(d1)); //"true" System.out.println(D.class.isInstance(d1)); //"true" System.out.println(D.class.isInstance(b1)); //"false" }

-Perché in Java deve valere il seguente vincolo: se o1.equals(o2) allora o1.hashcode()==o2.hashcode() -hashcode() restituisce un intero che deve essere calcolato facendo uso degli stessi campi usati nella verifica di uguaglianza profonda

_ Pattern per l'overriding di hashcode(): public class B { private int x, y; ...

public boolean equals(Object o) { if (o != null && getClass().equals(o.getClass())) { B b = (B)o; //test uguaglianza profonda return (x==b.x) && (y==b.y); //usa i campi x e y } else return false; }

public int hashcode() { return x+37*y; //funzione di hash //basata sui campi x e y } }

_ Overriding di equals() nelle classi derivate: Va effettuato richiamando prima l'equals() della classe base, e poi verificando l'uguaglianza dei campi propri della classe derivata

_ Pattern per l'overriding di equals() nelle classi derivate public class D extends B { private int z; ...

public boolean equals(Object o) { if (super.equals(o)){ D d = (D)o; //test uguaglianza profonda //dei campi propri della classe return z==d.z; } else return false; }

... }

_ Pattern per l'overriding di hashcode() nelle classi derivate public class D extends B { private int z; ... public boolean equals(Object o) { if (super.equals(o)){ //usa campi della classe base D d = (D)o; //test uguaglianza profonda //dei campi propri della classe return z==d.z; //più campi addizionali } else return false; }

public int hashcode() { return super.hashcode()+ //usa campi della classe base 53*z; //più campi addizionali } ... }

_ Copia di Oggetti: Possiamo effettuare una copia superficiale, ovvero una copia dell'identificatore di un oggetto Oppure possiamo effettuare una copia profonda, ovvero creiamo un nuovo oggetto che è un clone dell'oggetto originario (Identico ma con un diverso identificatore)

_ Esempio copia superficiale: public class C {…}

C c1 = new C(4,5); C c2; c2 = c1;

//c1, c2 sono uguali superficialemnte

_ Copia profonda con clone(): //Pattern per l'overriding di clone()

public class B implements Cloneable { private int x, y; ...

public Object clone() { try{ B b = (B)super.clone(); //copia profonda dei campi dati //incluse liste, array, ecc. return b; } catch(CloneNotSupportedException e) { throw new InternalError("..."); } }

... }

Osservazioni: super.clone() è l’invocazione al clone() di Object che crea un nuovo oggetto della stessa classe dell’oggetto di invocazione facendo copia superficiale dei campi dati

Si noti che questo comportamento corrisponde alla copia esatta della porzione di memoria dove è contenuto l’oggetto di invocazione, e non è ottenibile in nessun altro modo!

B b = (B)super.clone(); l’oggetto restituito da clone() è denotato da un riferimento di tipo Object attraverso il casting lo denotiamo con un riferimento del tipo giusto così da potere operare sui suoi campi

//copia profonda dei campi dati //incluse liste, array, ecc. super.clone() ha prodotto una nuovo oggetto con i campi che sono una copia superficiale dei campi dell’oggetto originario se siamo in presenza di campi per rappresentare, liste, array, ecc. dobbiamo farne la

Coppia c = new Coppia("ciao","mondo"); String primo = c.getPrimo(); String secondo = c.getSecondo(); ...

_ Tipi Generici Esempio: class C { private T info; public C(T info) { this.info=info; } public T getInfo() { return info; } public void setInfo(T info) { this.info=info; } }

... C c1 = new C("ciao"); C c2 = new C(new Persona(…)); String s = c1.getInfo(); Persona p = c2.getInfo(); ...

_ Nome dei parametri generici Per i nomi dei parametri di tipo formali si può utilizzare qualsiasi identificatore valido in Java, tuttavia esistono delle convenzioni che è bene conoscere ed utilizzare:

  • E - Elemento (usato estensivamente nel JCF)
  • K - Chiave
  • N - Numero
  • T - Tipo
  • V - Valore
  • S,U,V etc. - secondo, terzo e quarto parametro risp.

_ Tipi Generici: Cancellazione

  • I tipi generici esistono solamente fino a tempo di compilazione.
  • Quando il compilatore traduce la classe o il metodo generico:
    • Elimina la sezione del tipo parametrico e sostitusce le occorrenze con il tipo Object (a meno di vincoli sul tipo)
  • Inserisce automaticamente il cast esplicito dove richiesto.
  • Solo una copia della classe/metodo vengono creati nel byte code.
  • Questo meccanismo viene detto erasure (cancellazione)

_ Uso di classi Wrapper invece che tipi dato primitivi con Generics:

  • Poiché i tipi generici vengono rimpiazzati a tempo di compilazione da riferimenti a oggetti, non è possibile utilizzare tipi primitivi in fase di invocazione.
  • Per creare collezioni di tipi primitivi si possono utilizzare le corrispettive classi wrapper. Coppia c1 = new Coppia(1, 2); // Errore a tempo di compilazione Coppia c1 = new Coppia(1, 2); // Corretto; // N.B. autoboxing!

_ Interfacce del JCF: Collection Set SortedSet NavigableSet List Queue Deque BlockingQueue BlockingDeque

Map ConcurrentMap ConcurrentNavigableMap SortedMap NavigableMap

_ Interfacce e classi del JCF: Collection Set -HashSet -LinkedHashSet SortedSet -TreeSet NavigableSet List -ArrayList -LinkedList -Vector -Stack Queue -PriorityQueue Deque -ArrayDeque BlockingQueue BlockingDeque

Map ConcurrentMap ConcurrentNavigableMap SortedMap NavigableMap

_ Interfaccia Collection: public interface Collection { // Basic Operations int size(); boolean isEmpty(); boolean contains(Object element); boolean add(E element); // Optional boolean remove(Object element); // Optional Iterator iterator(); boolean equals(Object o);

// Bulk Operations boolean containsAll(Collection<?> c); boolean addAll(Collection<? extends E> c); // Optional boolean removeAll(Collection<?> c); // Optional boolean retainAll(Collection<?> c); // Optional void clear(); // Optional

// Array Operations Object[] toArray(); T[] toArray(T[] a); }

_ Interfaccia Set: public interface Set extends Collection {

} L'interfaccia Set non definisce alcuna nuova funzione