13. COMMENTI Java mette a disposizione tre modi per indicare i commenti : // Commento su una singola linea /* Commento su più linee, si può andare a capo, deve essere terminato con i caratteri */ /** Commento interpretato dalla utility Javadoc, in questo modo è possibile generare automaticamente una documentazione in html */ I commenti non possono essere nidificati.
14. VARIABILI Una variabile è un nome simbolico per una porzione di memoria. Prima di essere utilizzata, deve sempre essere dichiarata. Ogni variabile è caratterizzata da un tipo e da un nome. Java è un linguaggio fortemente tipizzato.
15. NOMI DI VARIABILI Il nome della variabile deve cominciare con una lettera dell’alfabeto o con uno dei seguenti caratteri: _ $ Per lettere si intendono i caratteri ‘a’-‘z’, ‘A’-‘Z’ e qualsiasi altro carattere Unicode che indichi una lettera in un lingua qualsiasi. I caratteri successivi al primo possono contenere anche cifre ‘0’-‘9’ Tutti gli altri caratteri non possono essere utilizzati (%,&,# ecc.). Non possono essere utilizzate parole riservate. Java è case sensitive : la variabile Var1 è diversa da var1 . Non ci sono limiti di lunghezza.
16. ESEMPI DI NOMI DI VARIABILI NOMI CORRETTI a abracadabra AbraCadabra abra_cadabra abra$ $abra abra1 è_abra_cadabra _abra NOMI ERRATI abra# abra-cadabra abstract 2abra abra*cadabra ?abra! abra cadabra abra&cadabra abra.cadabra
17.
18. PAROLE RISERVATE abstract boolean break byte case catch char class default false final for if implements import instanceof int interface long native new null package protected private public return short static super switch synchronized this throw throws transient true try void while
19.
20. TIPI PRIMITIVI Numerici interi byte 1 byte da -128 a 127 short 2 byte da -32.768 a 32.767 int 4 byte da -2.147.483.648 a 2.147.483.647 long 8 byte da –2 63 a 2 63 –1 Numerici a virgola mobile float 4 byte 3.4028234E+38 (7 cifre decimali significative) double 8 byte 1.79769313486231570E+308 (15 cifre decimali significative) Caratteri char 2 byte 65536 caratteri Unicode,39000 utilizzati Booleani boolean true,false
21.
22. ASEEGNAMENTO DI LETTERALI Interi sono considerati int per default 0 1 25 -12541 02 07 -0123 0x0 0x2a 0x1FF Virgola mobile sono considerati double per default 1.0 -47.1 1.22e19 3.16E-9 6.2f 2.14e-2f Boolean true false Caratteri ’a’ ’’ ’u0f6’
23. CODICI DI CARATTERE nuova riga tabulazione cancella il carattere a sinistra ritorno a capo avanzamento pagina backslash apice doppio apice
24.
25.
26. OPERATORE DI ASSEGNAMENTO Il simbolo = assegna l’espressione di destra alla variabile a sinistra : int var1=10; Un’ espressione è una istruzione che restituisce un valore. Le espressioni vengono sempre valutate prima di essere assegnate alle variabili. Le espressioni possono quindi contenere degli operatori: int var1=10+2; L’assegnamento può essere multiplo: var1=var2=var3=0;
27. OPERATORI DI BASE +,-,*,/,% / restituisce un numero intero se i due operandi sono interi restituisce un numero in virgola mobile se uno dei due operandi è in virgola mobile. % è l’operatore di modulo, restituisce il resto della divisione tra due interi: Es: 10% 3 = 1 - è usato anche per negare un operatore singolo. Non esiste l’elevamento a potenza, bisogna utilizzare una “funzione”.
28. ASSEGNAMENTI PARTICOLARI Sono assegnamenti combinati con operatori, la cui sintassi deriva dal C. Invece di utilizzare la seguente forma: a = a op b; op è un operatore Posso scrivere : a op = b; Es: a + = 2; // a=a+2; a * = -1; // a=a*(-1)
29.
30.
31. OPERATORI LOGICI Gli operatori logici possono agire solo su operandi, o espressioni, di tipo booleano. & && and | || or ^ xor ! not & e | valutano entrambe i membri dell’operatore && e || sono operatori condizionali, cioè valutano l’operando a destra solo in alcuni casi, dipendenti dall’operatore di sinistra. Es: (1>2) & (2>3) valuta entrambe le condizioni (1>2) && (2>3) valuta solo la prima condizione, essendo falsa, il risultato non può che essere falso (2>1)||(3<1) valuta solo la prima condizione, essendo vera, il risultato non può che essere vero
32. OPERATORI SUI BIT & and bit a bit | or bit a bit ^ xor bit a bit << scorrimento a sinistra >> scorrimento a destra >>> scorrimento a destra con riempimento di zeri ~ complemento bit a bit <<= scorrimento a sinsitra con assegnamento (x=x<<y) >>= scorrimento a destra con assegnamento (x=x>>y) >>>= scorrimento a destra con riempimento di zeri e assegnamento &= and con assegnamento |= or con assegnamento ^= xor con assegnamento
33. PRECEDENZE TRA GLI OPERATORI . [] () ++ -- ~ ! * / % + - << >> >>> < > <= >= == != & ^ | && || = += -= *= /= Gli operatori con la stessa precedenza sono eseguiti da sinistra a destra.
34.
35. BLOCCHI DI ISTRUZIONI Un blocco è un insieme di istruzioni racchiuse tra parentesi graffe {} I blocchi possono essere allo stesso livello o innestati. I blocchi definiscono l’ambito di validità (scope) delle variabili, una variabile definita in un blocco non è visibile all’esterno ma lo è nei blocchi contenuti, quando si esce dal blocco la variabile viene eliminata. Non è possibile dichiarare due variabili con lo stesso nome all’interno dello stesso blocco o in due blocchi diversi ma innestati tra di loro.
36.
37.
38.
39.
40. SWITCH L’istruzione switch permette di scegliere una tra più alternative. La variabile utilizzata per il confronto può essere char, byte, short, int, non si possono utilizzare float,double e oggetti ( e quindi stringhe) tranne le classi wrapper dei tipi primitivi (Integer, …) switch(variabile){ case const_1 : istruzione1; break; case const_2 : istruzione2; break; default : istruzione3; } const_1 e const_2 devono essere dei letterali, non possono essere delle variabili. L’istruzione break serve per uscire dallo switch.
41. FOR Il ciclo for permette di ripetere un’istruzione o un blocco di istruzioni, un numero prefissato di volte. La forma generale di un ciclo Java è la seguente: for (inizializzazione;condizione;incremento){ istruzioni; } inizializzazione : è un’espressione eseguita all’avvio del ciclo condizione: è la condizione valutata ad ogni ripetizione incremento: è un espressione eseguita alla fine di ogni ciclo Questi parametri non sono obbligatori, possono anche essere omessi. L’inizializzazione e l’incremento possono comprendere più espressioni separate da virgole.
42. FOR - Esempi for (int i = 0; i < 10; i++) { System.out.println(i); } for (int i = 0; i < 10; ) { System.out.println(i++); } int i = 0; for (; i < 10; ) { System.out.println(i++); }
43. FOR EACH Questo costrutto è stato inserito nel jdk 5 Permette di iterare su array o collezioni, o su oggetti che implementano l’interfaccia Iterable. for( type var : arr ){ <corpo> } for( type var : coll ){ <corpo> } for(int i =0;i< arr .length; i ++){ type var=arr[i]; <corpo> } for(Iterator iter = coll .iterator(); iter .hasNext(); ){ type var = iter .next(); <corpo> }
44.
45.
46.
47.
48. ETICHETTE Sia break che continue possono recare un’etichetta, l’etichetta indica un ciclo e specifica da quale ciclo devono uscire in presenza di cicli nidificati. break etichetta; continue etichetta; L’ etichetta va posta all’inizio del ciclo con la seguente forma: etichetta:
49.
50.
51. ASTRAZIONE Procedimento tendente a sostituire con una formula o con simboli la concreta molteplicità del reale (Devoto-Oli) I linguaggi di programmazione sono astrazioni della macchina su cui operano. I problemi da risolvere sono astrazioni della realtà. Abbiamo quindi uno spazio dei problemi e uno spazio delle soluzioni e dobbiamo trovare una relazione tra i due. OT permette di avere una relazione di tipo lineare.
52. PROGRAMMAZIONE ORIENTATA AGLI OGGETTI E’ una tecnica (modello di programmazione) che punta i riflettori sui dati (oggetti) e quindi su come agire su di essi. La programmazione tradizionale parte invece dagli strumenti e successivamente si preoccupa dei dati. Si basa sullo sviluppo di componenti software completi, denominati oggetti. Questi oggetti sono modellati sulla base delle cose che si vedono nel mondo reale. Gli oggetti sono definiti in termini di informazione che contengono e di operazioni che forniscono per l'uso e la manipolazione di tali informazioni.
53. OGGETTI Una lampada è un oggetto, che contiene informazioni relative al suo stato (accesa o spenta) e metodi per accedere allo stato della lampada (accendi o spegni). L'informazione contenuta nell'oggetto, indipendentemente dal suo stato, rappresenta i dati dell'oggetto. Alcuni metodi dell'oggetto forniscono informazioni relative ai dati dell'oggetto (accesso in lettura), altri consentono di modificare i dati (accesso in scrittura) e altri ancora di creare gli oggetti (constructor).
54. METODOLOGIA ORIENTATA AGLI OGGETTI Oggetti: sono le cose. Classi: definizione delle cose. Individuare: - quali classi e oggetti esistono - la loro struttura, il loro comportamento e l'utilizzo - le relazioni che esistono tra le classi e tra gli oggetti
55. OGGETTO per OT è un'astrazione di un oggetto reale per il software è una struttura dati con funzioni associate Gli oggetti fanno qualcosa (una penna scrive). Gli oggetti mantegono al loro interno informazioni sullo stato: queste informazioni sono dette attributi (quantità di inchiostro in una penna). Gli oggetti sono unici (come una riga di un database). Gli oggetti possono essere formati da altri oggetti.
56. CLASSI Una classe è l'insieme delle specifiche di tutte le operazioni, di tutti gli attributi e di tutti i legami con altri oggetti per un determinato tipo di oggetto. Si dice che un oggetto è un'istanza di una classe, con particolari valori degli attributi. Le classi permettono di pensare a concetti -> livello superiore di astrazione che permette la classificazione. La classe è una definizione, un oggetto, invece, esiste a runtime. La classe è il progetto, mentre l’oggetto è la costruzione reale fatta seguendo il progetto
58. INCAPSULAMENTO Meccanismo che serve a nascondere come un oggetto è fatto, noi operiamo con l'oggetto tramite le operazioni (interfaccia). (Esempio bancomat, cambio il software o l'hardware ma il funzionamento non cambia). L'incapsulamento è una caratteristica importante per lo sviluppo di software affidabile.
59. EREDITARIETA’ Le classi possono avere in comune delle caratteristiche -> ereditarietà è un rapporto tra le classi (valivolo ed aereo o elicottero). E' un meccanismo che velocizza la produzione del software poiché nuove classi possono essere derivate a partire da classi esistenti: la sottoclasse deve avere il comportamento della superclasse.
60. CLASSIFICAZIONE La classificazione è un metodo molto diffuso utilizzato per l'organizzazione della conoscenza. Se una data categoria di oggetti compare nell'albero di classificazione, essa soddisfa le propreità di tutte le categorie di oggetti che si trovano ad un livello superiore dell'albero. Il fatto che una categoria di livello inferiore condivida tutte le caratteristiche delle categorie che si trovano 'sopra' è noto come ereditarietà. Si dice che una classe A estende un'altra classe B se contiene tutti i dati contenuti nella classe B e implementa tutti i metodi implementati dalla classe B. La classe A è detta sottoclasse della classe B e la classe B è detta superclasse della classe A. Se una classe è sottoclasse di un'altra classe eredita tutti i dati e i metodi della superclasse.
61. EREDITARIETA’ MULTIPLA Quando una classe estende diverse classi appartenenti a differenti diramazioni dell'albero si parla di ereditarietà multipla. Il problema maggiore è dato dalla difficoltà di determinare quale superclasse utilizzare in determinate condizioni. Java non supporta l'ereditarietà multipla, solo ereditarietà singola. I vantaggi dell'ereditarietà multipla sono ottenuti tramite le interfacce.
62. POLIMORFISMO Il polimorfismo è la capacità degli oggetti di assumere “forme” e quindi comportamenti differenti all’interno di una gerarchia Questo meccanismo viene realizzato mediante due meccanismi: overloading e overriding. Per poter utilizzare questi meccanismi è necessario uno specifico supporto della virtual machine
63. COLLEGAMENTO DINAMICO La capacità di rinviare fino al momento di runtime decisioni sulla classe alla quale appartiene un oggetto e sui metodi di accesso all'oggetto è nota come collegamento dinamico. Il compilatore e l'interprete lavorano congiuntamente in modo da fornire un codice eseguibile con le capacità necessarie per interfacciarsi dinamicamente con oggetti sconosciuti durante l'esecuzione del programma.
64. JAVA Java è un linguaggio di programmazione orientato agli oggetti puro. In Java ci sono dei tipi di dato primitivi. Per creare delle strutture dati è necessario utilizzare gli oggetti. Gli oggetti si compongono di dati: attributi, variabili di istanza o stato e di comportamenti (funzionalità): operazioni o metodi di istanza. Gli oggetti sono istanze delle classi.
65.
66.
67.
68.
69.
70. ACCEDERE ALLE PROPRIETA’ Si accede alle proprietà di un oggetto attraverso il nome del riferimento e l’operatore ‘ . ’ (punto). Esempio: ContoCorrente cc = new ContoCorrente(); cc.codice = 1023; … . if (cc.saldo < 0) cc.saldo = 0;
71. ACCEDERE AI METODI Si accede ai metodi di un oggetto attraverso il nome del riferimento e l’operatore ‘ . ’ (punto). Esempio ContoCorrente cc = new ContoCorrente(); cc.codice = 1023; … . if (cc.saldo < 0) cc.versare (10000);
72. PASSAGGIO DEI PARAMETRI Solitamente su questo argomento si dice: Le variabili di tipo primitivo sono passate per valore (copia). La variabili di tipo oggetto sono passate per riferimento (side effects). In realtà non è così, tutto è passato per valore, nel caso degli oggetti viene passato per valore il riferimento all’oggetto. Quindi viene copiato il “puntatore” all’oggetto, ma l’oggetto riferito è sempre lo stesso.
73. VARIABLE ARGUMENTS (VARARGS) Introdotti dal jdk 5. Nel caso in cui il numero dei parametri non sia conosciuto a priori, posso passare una collezione di parametri o un array, oppure dichiarare un numero variabile di argomenti. public void metodo(<tipo>... nome){ All’interno del metodo, i valori sono raggruppati in un array. public int sum(int... intList){ int ret=0; for(int val:intList) { ret +=val; } return(ret); } Ci può essere solo una serie di parametri variabili, e deve essere come ultimo parametro nel metodo
74. PACKAGE I programmi Java sono organizzati in pacchetti (unità di compilazione). I pacchetti contengono il codice sorgente delle dichiarazioni di classe e di interfaccia. I pacchetti sono identificati dall'istruzione package, la prima in un file sorgente. package nomePacchetto; Se l'istruzione viene omessa, le classi e le interfacce dichiarate all'interno del pacchetto vengono inserite nel pacchetto predefinito, quello senza nome che è unico all'interno di una directory. Il nome del pacchetto e la variabile di ambiente CLASSPATH vengono usate per trovare una classe.
75. L’ISTRUZIONE IMPORT L'istruzione import è utilizzata per fare riferimento a classi e interfacce che sono dichiarate in altri pacchetti. Esistono tre forme di import: import nomePacchetto.NomeClasse; import nomePacchetto.*; La prima consente di far riferimento alle classi e interfacce identificate senza specificare il nome del relativo pacchetto. La seconda consente di far riferimento a tutte le classi e le interfacce contenute nel pacchetto senza specificare il nome del relativo pacchetto. In alternativa è possibile qualificare completamente l’oggetto da utilizzare: nomePacchetto.NomeClasse.metodo()
76. STATIC IMPORT Dalla versione 5 è stata inserita l’opzione import static che permette di referenziare variabili statiche (tipicamente costanti) senza doverle qualificare con il nome della classe. Es: import static java.awt.Color; è quindi possibile scrivere: Color background = RED; invece di Color background = Color.RED; E’ comunque sconsigliabile utilizzarlo.
77. INCAPSULAMENTO La dichiarazione di una proprietà o di un metodo può essere preceduta da un modificatore di accesso: private Public Esempio class ContoCorrente{ private int saldo; public void setSaldo (int valore){ saldo = valore; } public int getSaldo () { return saldo; } }
78. IL RIFERIMENTO ‘THIS’ Il riferimento this può essere utilizzato per risolvere ambiguità sui nomi delle variabili o per operazioni di callback. Esempio class ContoCorrente{ private int saldo; public void setSaldo (int saldo){ this.saldo = saldo; } public int getSaldo (){ return saldo; } public void stampa() { Stampa st = new Stampa(); st.eseguiStampa (this); } }
79. OVERLOADING DEI METODI All’interno di una classe è possibile definire metodi con lo stesso nome, lo stesso valore di ritorno ma una diversa lista di argomenti. Il compilatore analizzando i parametri della chiamata sceglie quale metodo deve essere invocato. class ContoCorrente{ private int saldo; public void setSaldo (int saldo){ this.saldo = saldo; } public void setSaldo (){ this.saldo = 12000; } public int getSaldo () { return saldo; } }
80. COSTRUTTORI Metodi speciali per fornire una inizializzazione ad hoc delle proprietà. Sono chiamati quando si crea un oggetto con l’istruzione new. Hanno lo stesso nome della classe, possono avere una lista di parametri, ma non devono specificare un valore di ritorno. Il compilatore fornisce un costruttore di default senza argomenti.
81. COSTRUTTORI Se definisco un altro costruttore, il costruttore di default (implicito) viene ‘perso’ ed eventualmente devo definirlo esplicitamente. Un costruttore può richiamare un altro costruttore, ma può essere solo la prima istruzione eseguita. Si possono richiamare altri costruttori della stessa classe o costruttori della superclasse. Se non specifico altrimenti, il costruttore della sottoclasse richiama il costruttore di default della superclasse.
82. USO DI THIS TRA COSTRUTTORI Esempio public ContoCorrente (int saldo, boolean attivo){ this.saldo = saldo; this.attivo = attivo; } // Non corretta public ContoCorrente (int saldo){ this.saldo = saldo; this.attivo = true; } // Corretta public ContoCorrente (int saldo){ this(saldo, true); }
83. PROPRIETA’ DI CLASSE Appartengono ad una classe e sono quindi comuni a tutte le istanze di una classe. Sono dichiarate con la parola riservata static . Hanno valori di default nell’inizializzazione come le propietà delle istanze. Inizializzazioni complesse tramite un blocco static . Si accede ad esse tramite il nome della classe: ContoCorrente.tassoInteresse = 0.05;
84. METODI DI CLASSE Appartengono ad una classe e sono quindi utilizzati da tutte le istanze di una classe. Sono dichiarati con la parola riservata static . Servono per accedere alle proprietà statiche (di classe). Si utilizzano per creare librerie di funzioni. Si accede ad esse tramite il nome della classe. ContoCorrente.setTassoInteresse (0.05); double a = Math.sqrt(b);
85. PROPRIETA’ FINAL Il modificatore final definisce una proprietà che non puà essere modificata, posso assegnarla un valore solo la prima volta. Non può essere modificata. Deve essere inizializzata. Viene quindi utilizzato per le costanti. Esempio: class ContoCorrente { private int saldo; public static final int maxPrelievo = 3000000; public ContoCorrente (int saldo){ this.saldo = saldo; } }
86. METODI E CLASSI final Un metodo definito come final non può essere ridefinito. Una classe definita final non può essere estesa. Esempi public final class Color{ …… } public final boolean controllaPassword (String p) { … .. }
87. EREDITARIETA’ L’ereditarietà è quel meccanismo della OOP che permette di definire una classe specificando soltanto quello che la differenzia da un’altra classe. E’ una tecnica che incoraggia a riutilizzare il software. La classe originale è detta superclasse. La classe derivata è detta sottoclasse .
88. EREDITARIETA’ IN JAVA Parola riservata extends Nella definizione di una classe va indicato quale classe estende. Una sola classe poiché l’ereditarietà è singola. Se non si dichiara la superclasse di una classe vuol dire che la superclasse è Object. Esempio: class Taxi extends Auto{ String licenza; }
89. CARATTERISTICHE DELLA SOTTOCLASSE La sottoclasse eredita automaticamente tutte le caratteristiche (proprietà e metodi) della superclasse. Auto a = new Auto; … Taxi t = new Taxi(); L’oggetto t avrà tutte le proprietà della classe Auto. Le proprietà della classe Auto che sono private non sono accessibili direttamente dagli oggetti della classe Taxi.
90. MODIFICATORI Modificatore public Gli attributi e i metodi preceduti da questo modificatore sono accessibili da tutte le altre classi. Modificatore protected Gli attributi e i metodi preceduti da questo modificatore sono accessibili da tutte le classi del package, dalle stottoclassi del package e dalle sottoclassi esterne al package.
91. MODIFICATORI Modificatore private Gli attributi e i metodi preceduti da questo modificatore sono accessibili solamente dalla stessa classe. Modificatore di default Gli attributi e i metodi che non sono preceduti da alcun modificatore sono accessibili da tutte le classi del package e dalle stottoclassi del package .
92. MODIFICATORI no no sì sì da una sottoclasse esterna al package no sì sì sì da una sottoclasse dello stesso package no no no sì da una qualsiasi classe esterna al package no sì sì sì da una qualsiasi classe dello stesso package sì sì sì sì dalla stessa classe private default protected public Visibilità
93. METODI DELLA SOTTOCLASSE I metodi di una superclasse sono utilizzabili da tutte le sottoclassi. Class Taxi extends Auto{ private String licenza; public void setLicenza (String licenza){ this.licenza = licenza; } public String getLicenza(){ return licenza; } } ……… ……… Taxi t = new Taxi(); t.setLicenza (“QW 987 YTR”); t.setTarga(“AD 098 BV”);
94. OVERRIDING Una sottoclasse eredita tutti i metodi di una superclasse. Una sottoclasse può sovrascrivere (ridefinire) un metodo ereditato, definendo di nuovo il metodo con lo stesso nome, lo stesso valore di ritorno e la stessa lista dei parametri. Il metodo sovrascritto nasconde il vecchio metodo presente nell’albero di ereditarietà. L’overriding non può variare il modificatore in maniera meno restrittiva.
95. INVOCARE UN METODO DELLA SUPERCLASSE Un metodo sovrascritto nasconde il vecchio metodo definito nella superclasse. La parola riservata super permette di far riferimento al metodo definito nella superclasse. Esempio public void visualizza(){ super.visualizza(); System.out.println(“Targa: “ + targa); }
96. USO DI SUPER TRA COSTRUTTORI Un costruttore di una sottoclasse può invocare un particolare costruttore della superclasse. La chiamata al costruttore della superclasse deve essere al primo posto nel codice del costruttore della sottoclasse. Esempio di costruttore public Taxi (String targa, String licenza){ super (targa); this.licenza = licenza; }
97. ASSEGNAMENTI TRA CLASSE E SOTTOCLASSE Ad un riferimento della superclasse si può assegnare un riferimento di una sottoclasse, poiché la sottoclasse è “del tipo della” superclasse. Esempio Auto a = new Taxi (“AD 098 YT”, “NUM 4563”); Non si può assegnare ad un riferimento di una sottoclasse un oggetto della superclasse.
98. SOSTITUZIONE DI RIFERIMENTI Dove è richiesta una superclasse posso sempre passare una sottoclasse. Esempio public void stampa (Auto a) { a.visualizza(); } Taxi t = new Taxi(“AY 765 OP”, “NUM 3456”); Auto a = new Auto (“AD 098 TY”); stampa (a); stampa (t);
99. L’OPERATORE instanceof L’operatore instanceof serve per determinare il tipo esatto di un oggetto. Ha come operandi un oggetto e una classe, restituisce un valore booleano. Si può effettuare un’operazione di downcast verso il tipo corretto, se è necessario. Serve per poter invocare metodi specifici del tipo corretto. Esempio: if (c instanceof Taxi) ((Taxi) c).setLicenza (“NUM 23425”);
100. POLIMORFISMO Un riferimento ad oggetto può avere a runtime un tipo diverso di quello dichiarato, cioè può appartenere ad una sottoclasse del tipo dichiarato. Quale metodo verrà chiamato dipende dal tipo effettivo di un oggetto: questo è il polimorfismo ed è possibile grazie al collegamento dinamico. Il metodo che verrà chiamato non viene deciso al momento della compilazione del programma, ma a runtime.
101. ESEMPIO Una collezione polimorfica. Auto a[] = { new Auto(“AD 234 YT”), new Taxi (“AC 123 KJ”, “NUM 9876”) } for (int i=0; i<a.length; i++) a[i].visualizza();
102. CLASSI ASTRATTE Forniscono un’implementazione parziale di alcuni concetti. Sono superclassi talmente generali, che vengono utilizzate solo come un framework per le sottoclassi. Una classe astratta non può essere istanziata.
103. LA PAROLA RISERVATA abstract Per dichiarare una classe astratta si usa la parola riservata abstract. public abstract class Veicolo { private String targa; public String getTarga() { return targa; } public void setTarga(String targa) { this.targa = targa; } } ……… . public class AutoTreno extends Veicolo { private int carico; ………… }
104. METODO ASTRATTO E’ un metodo che non può essere implementato da una classe. Fa parte di una classe astratta. Deve essere implementato da una sottoclasse concreta (non astratta). Ogni sottoclasse lo può implementare in maniera differente.
105. DEFINIZIONE DI METODI ASTRATTI La classe deve essere abstract. public abstract class Veicolo { public abstract boolean collaudato(); …… } Si stabilisce il nome del metodo, la lista dei parametri e il tipo del valore di ritorno. Le sottoclassi concrete implementeranno o sovrascriveranno il metodo.
106. POLIMORFISMO Si possono definire delle collezioni polimorfiche (tipi differenti) utilizzando le classi astratte. Veicolo v[] = { new Auto(); new Autocarro(); }; for (int i=0; i<v.length; i++) if (v[i].collaudato()) ……
107. INTERFACCIA Sono delle raccolte di comportamenti astratti (non implementati) che possono essere combinati in una qualunque classe al fine di aggiungere un comportamento non fornito dalle sue superclassi. Esempio: il poter sterzare.
108. INTERFACCE Le interfacce sono come classi completamente astratte. Tutti i metodi sono astratti, cioè definiti come : public abstract. Tuttte le variabili sono definite come : public static final. Un’interfaccia definisce un insieme di metodi che possono essere implementati da altre classi. Una classe può estendere una sola classe ma può implementare più interfacce.
109. DEFINIZIONE DI INTERFACCIA Per definire un’interfaccia si utilizza la parola riservata interface . public interface Guidabile { int ANGOLO_MAX = 135; void giraDestra(int gradi); void giraSinistra(int gradi); } Metodi: public abstract Proprietà: public static final
110. IMPLEMENTARE UN’INTERFACCIA Clausola implements public class Auto extends Veicolo implements Guidabile { …… public void giraDestra(int gradi) { … } public void giraSinistra(int gradi) { … } } Se un classe non implementa tutti i medoti di un’interfaccia deve essere dichiarata astratta.
111. POLIMORFISMO CON INTERFACCE Quando faccio riferimento ad una classe che implementa una interfaccia, posso anche utilizzare l’interfaccia. Guidabile g; g può essere un riferimento a qualsiasi oggetto che appartiene ad una classe che implementa l’interfaccia Guidabile void viaggia (Guidabile g){ …… . g.giraDestra(120); }
112. USO DI instanceof Può essere utilizzato per verificare se un oggetto implementa un’interfaccia. public metodoA (Object obj) { if (obj instanceof Guidabile) ((Guidabile)obj).giraSinistra(110); }
113. ARRAY Un array è un mezzo per contenere una serie di variabili dello stesso tipo. Un array è un oggetto, non è un tipo primitivo. Posso vederlo come un insieme di celle di memoria contigue, ognuna delle quali contiene un valore. Es. array di 5 interi Un array può contenere tipi primitivi o oggetti. Ogni elemento dell’array può contenere un solo valore. In Java le dimensioni degli array possono essere definite in fase di runtime. 3 11 9 7 2
114. DEFINIZIONE DI ARRAY E’ necessario dichiarare l’array utilizzando le parentesi quadre, posso metterle sia dopo il tipo che dopo il nome dell’array. String[] nomi; String nomi[]; Bisogna quindi creare l’array con l’operatore new nomi=new String[5]; L’operatore new inizializza i singoli valori dell’array come per gli attributi di istanza. Posso anche creare un’array assegnando a tutti i suoi componenti un valore String[] nomi={“pippo”,”pluto”,”nonna papera”};
115. DEFINIZIONE DI ARRAY Per accedere agli elementi dell’array bisogna specificarne la posizione all’interno delle parentesi quadre. nomi[1]=”paperino”; System.out.println(nomi[3]); Se devo creare degli array di oggetti, oltre ad applicare l’operatore new all’array, lo devo applicare anche ai singoli componenti dell’array, devo cioè creare i singoli oggetti che poi formano il mio array. Auto[] mieAuto=new Auto[5]; mieAuto[1]=new Auto();
116. ARRAY MULTIDIMENSIONALI Un array multidimensionale è realizzato come array di array. Vediamo per esempio un array in due dimensioni, possiamo rappresentarlo come una matrice. int [][] array=new int[4][5]; Posso creare anche un array mutidimensionale non regolare: int[][] array=new int[5][]; int cont=0; a[0]=new int[++cont]; a[1]=new int[++cont]; a[2]=new int[++cont];
117. STRINGHE In java le stringhe sono degli oggetti, istanze della classe String. La classe String supporta solo stringhe costanti (non modificabili) String str= " test " ; è equivalente a : String str=new String( " testo " ); E’ il compilatore che sostituisce la seconda sintassi alla prima. Questo permette di avere una gestione più flessibile. Per concatenare le stringhe si usa l’operatore + String s= "" ; s=s+ " a " + " b " ;
120. StringBuffer La classe StringBuffer permette di gestire le stringhe variabili. Il compilatore sostituisce automaticamente oggetti di tipo String con oggetti di tipo StringBuffer nei casi necessari. String s=””; s=s+”a”+”b”; viene sostituito con : String s=””; s=new StringBuffer(””).append(”a”).append(”b”).toStrong(); E’ fondamentale utilizzare questa classe ogni volta che vengono fatte elaborazioni pesanti sulle stringhe.
121. CLASSI DI COPERTURA I tipi primitivi non sono oggetti, quindi non possono essere passati come argomenti dove sono richiesti oggetti. Esistono delle classi di copertura (wrapper), una per ogni tipo primitivo.
122. BOXING E UNBOXING Ogni classe wrapper definisce: • un costruttore che accetta il valore primitivo da incapsulare • un metodo che restituisce il valore primitivo incapsulato • Per incapsulare un valore primitivo (BOXING) – Integer i = new Integer( valore int ) – Double d = new Double( valore double ) – Character c = new Character( valore char ) • Per estrarre il valore incapsulato (UNBOXING): – Integer fornisce il metodo intValue() – Double fornisce il metodo doubleValue() – Character fornisce il metodo charValue() Integer i = new Integer(33); // boxing int k = i.intValue(); // unboxing
123. WRAPPER E OPERAZIONI Le classi wrapper non hanno operatori aritmetici new Integer(3) + new Integer(2); // ERRORE Quindi, per operare su due valori incapsulati in oggetti wrapper, in linea di principio occorre: – estrarre i valori incapsulati ( unboxing ) – svolgere le operazioni su essi, – costruire un oggetto per il valore risultato (boxing) Integer z =new Integer(x.intValue() + y.intValue());
124. BOXING AUTOMATICO In Java 1.5, boxing e unboxing di valori primitivi diventano automatici. Quindi, ora si può scrivere: Integer x = new Integer(ix); Integer y = new Integer(4); Integer z = x + y; perché la conversione da Integer a int degli operandi (unboxing) e la successiva conversione del risultato in Integer (boxing) sono automatiche.
125. BOXING AUTOMATICO Analogamente è quindi possibile inserire valori primitivi in strutture dati che accettano Object: List l = new ArrayList(); l.add(21); // OK in Java 1.5 perché viene attuata automaticamente la conversione da int a Integer (boxing) dal valore primitivo 21. Fino a Java 1.4.2, avremmo invece dovuto scrivere: l.add(new Integer(21)); facendo quindi esplicitamente l’operazione di boxing.
126.
127. BigDecimal Non è possibile fare questo: BigDecimal b1=new BigDecimal(2); BigDecimal b2=new BigDecimal(3); BigDecimal b3=b1+b2; // ERRORE Si possono solo usare metodi: BigDecimal b3=b1.add(b2); BigDecimal b4=b1.multiply(b2);
128. BigDecimal Per impostare una precisione è necessario definire un MathContext MathContext(int setPrecision) E utilizzarlo nella costruzione degli oggetti e nelle operazioni MathContext mc = new MathContext(2); BigDecimal b1=new BigDecimal(10,mc); BigDecimal b2=new BigDecimal(3,mc); BigDecimal b3=b1.add(b2); BigDecimal b4=b1.divide(b2,mc); Nella divisione conviene sempre usarlo, altrimenti le divisioni che hanno un numero infinito di decimali non possono essere arrotondate e generano una eccezione
129. Object La classe Object definisce una serie di metodi che possono essere ridefiniti all’interno delle classi figlie. boolean equals(Object obj) Indicates whether some other object is "equal to" this one. String toString() Returns a string representation of the object. protected Object clone() Creates and returns a copy of this object.
130. Confronto tra oggetti L’operatore == confronta correttamente i tipi primitivi. Per gli oggetti restituisce true se i due oggenti confrontati sono la stessa istanza. Per valutare se due istanze diverse sono uguali, è necessario utilzzare il metodo equals, ovviamente questo deve essere ridefinito nelle classi su cui si vuole utilizzare. String a=”Stringa”; if(a.equals(”Stringa”)){ return true; } Per le stringhe esiste anche il metodo : public boolean equalsIgnoreCase(String anotherString)
131. Confronto tra oggetti Cosa produce il seguente esempio? String s1="ciao"; String s2="ciao"; System.out.println(s1==s2); s1=s1+s2; s2=s2+s2; System.out.println(s1==s2);
132. Date Per la gestione delle date esiste la classe java.util.Date Permette di memorizzare sia la data che l’ora new Date(); Costruisce una data partendo dai millisecondi correnti. Gli unici metodi utilizzabili sono after() before() compare() Tutti gli altri metodi sono deprecati. Per gestire la costruzione e la manipolazione delle date deve essere utilizzata la classe Calendar, oppure nei casi più semplici la classe SimpleDateFormat
133. SimpleDateFormat Permette di interpretare o di formattare le date. SimpleDateFormat(String pattern) String format(Date date) Date parse(String source) Date d1=new Date(); SimpleDateFormat sdf= new SimpleDateFormat("dd/MM/yyyy"); System.out.println(sdf.format(d1)); Date d2=null; try { d2 = sdf.parse("01/02/2010"); } catch (ParseException e) { e.printStackTrace(); }
134. Calendar Permette di manipolare le date. Per ottenere una istanza di calendar Calendar cal=Calendar.getInstance(); Per valorizzare il calendar con la data specifica void setTime(Date date) Per eseguire operazioni sulle date void add(int field, int amount) Per ottenere un campo della data int get(int field) Per settare un campo della data void set(int field, int value)
135. GESTIONE DEGLI ERRORI Se un’operazione non può essere completata perché si è verificato un errore, il programma dovrebbe: Tornare in uno stato normale e consentire all’utente di eseguire altri comandi, oppure Salvare il lavoro e terminare il programma in modo appropriato Il compito di un gestore di eccezioni consiste nel trasferire il controllo dal punto in cui si è verificato l’errore ad un punto che sia in grado di risolvere o gestire l’errore.
136.
137.
138. ECCEZIONI I metodi di Java generano un’eccezione se per qualche ragione falliscono il loro scopo. L’eccezione è un oggetto, e quando viene generato viene messo in cima allo stack delle chiamate. Quindi, il metodo viene interrotto e la VM cerca nello stack delle chiamate un metodo che sia in grado di gestire quel particolare tipo di eccezione.
140. ECCEZIONI Error descrivono gli errori interni del sistema run-time di Java, non devono essere gestiti. Le Runtime Exception derivano da errori di run-time come: errata conversione di tipo, accesso errato ad un array ... , non dovrebbero essere gestite, dovrebbe essere applicata una gestione preventiva. Queste eccezioni sono dette unchecked e non vengono controllate a compile time Tutte le altre eccezioni vanno gestite. Sono detta checked e sono controllate a compile time, per questo devono obbligatoriamente essere gestite.
144. CATTURARE LE ECCEZIONI Se si chiama un metodo che può generare un’eccezione, bisogna fare in modo che questa eccezione possa essere gestita, per fare questo si usa la seguente struttura: try { // codice che può generare l’eccezione }catch (tipo_di_eccezione_1) { // codice del gestore dell’eccezione } Quando si verifica un’eccezione all’interno del try, questa viene rilevata e se è del tipo indicato nel catch, il controllo viene passato al relativo codice. Quindi il controllo passa alla riga di codice successiva alla fine del catch.
145. ECCEZIONI MULTIPLE E’ possibile che un metodo generi più di una eccezione, in questo caso bisogna aggiungere tante clausole catch quanti sono i tipi di eccezioni che vanno gestiti : try { // codice che può generare l’eccezione }catch (tipo_di_eccezione_1 e1) { // codice del gestore dell’eccezione 1 }catch (tipo_di_eccezione_2 e2) { // codice del gestore dell’eccezione 2 } Se più eccezioni derivano dalla stessa classe, possiamo raccoglierle e gestire solamente la superclasse.
146. CLAUSOLA FINALLY Se vogliamo che una parte del codice venga eseguita comunque, anche nel caso in cui vengano generate delle eccezioni, bisogna inserire la clausola finally: try { // codice che può generare l’eccezione }catch (tipo_di_eccezione_1) { // codice del gestore dell’eccezione 1 }finally { // codice sempre eseguito } E’ importante notare che finally non è una clausola per gestire tutte le eccezioni che non sono gestite dalle singole catch.
147. GESTIONE DELLE ECCEZIONI La struttura try-catch gestisce localmente le eccezioni, cioè all’interno del metodo in cui si sono verificate. E’ possibile non gestire l’eccezione a questo livello e passarla al metodo che aveva chiamato il metodo in questione. Per fare questo, i metodi che vogliono passare le eccezioni, devono dichiarare che tipo di eccezioni possono restituire tramite la parola chiave throws : public void metodo1() throws tipo_di_eccezione{ // codice del metodo } In questo modo la gestione delle eccezioni risale la gerarchia dei metodi dello stack.
148. GENERARE ECCEZIONI Un metodo deve dichiarare che al suo interno può aver luogo una eccezione, la sintassi è la stessa del caso precedente. Per generare un’eccezione, bisogna utilizzare la parola chiave throw. In questo modo, in qualunque parte del codice si può generare un’eccezione. Prima di essere “lanciata”, essendo un oggetto, l’eccezione va sempre creata con una new. throw new IOException(); oppure IOException eccez=new IOException(); throw eccez;
149. CREARE CLASSI ECCEZIONI Devono estendere la classe Exception o le sue sottoclassi. Solitamente le classi eccezioni hanno due costruttori, uno di default e uno con il messaggio di errore. class MiaEccezione extends IOException{ public MiaEccezione() {} public MiaEccezione(String msg){ super(msg); } } void mioMetodo(DataInput in) throws MiaEccezione{ // codice if(condizione_di_errore) throw new MiaEccezione(); }
150. GESTIONE COMBINATA DELLE ECCEZIONI A volte è necessario gestire localmente l’eccezione e nello stesso tempo propagarla al metodo chiamante, questo meccanismo può essere realizzato catturando l’eccezione localmente, e quindi rigenerando l’eccezione che passa al metodo chiamante. void metodoChiamante() throws MiaEccezione{ try{ mioMetodo(mioDataInput) } catch (MiaEccezione e) { System.out.println(e.getMessage()); // gestione locale dell’eccezione throw new MiaEccezione(e.getMessage()); // propaga l’eccezione al chiamante } }
151.
152. JAVA COLLECTION FRAMEWORK Interfacce fondamentali (package java.util) • Collection: nessuna ipotesi su elementi duplicati o relazioni d’ordine • List: introduce l’idea di sequenza • Set: introduce l’idea di insieme di elementi (quindi, senza duplicati) • SortedSet: l'insieme ordinato • Map: introduce l’idea di mappa, ossia di funzione che associa chiavi (identificatori univoci) a valori • SortedMap: la mappa ordinata Criteri-guida per la definizione delle interfacce: • Minimalità – prevedere solo metodi davvero basilari… • Efficienza – …o che migliorino nettamente le prestazioni
153. JAVA COLLECTION FRAMEWORK Implementazioni fondamentali • per le liste: ArrayList,LinkedList, Vector • per le tabelle hash: HashMap, HashSet, Hashtable • per gli alberi: TreeSet, TreeMap
155. COLLECTION - SET boolean add(E e) Adds the specified element to this set if it is not already present (optional operation). boolean contains(Object o) Returns true if this set contains the specified element. boolean isEmpty() Returns true if this set contains no elements. Iterator<E>iterator() Returns an iterator over the elements in this set. boolean remove(Object o) Removes the specified element from this set if it is present int size() Returns the number of elements in this set (its cardinality).
156. LIST void add(int index, E element) Inserts the specified element at the specified position E get(int index) Returns the element at the specified position in this list. int indexOf(Object o) Returns the index of the first occurrence of the specified element in this list, or -1 if this list does not contain the element. int lastIndexOf(Object o) Returns the index of the last occurrence of the specified element in this list, or -1 if this list does not contain the element. E remove(int index) Removes the element at the specified position in this list E set(int index, E element) Replaces the element at the specified position in this list with the specified element
157. MAP boolean containsKey(Object key) Returns true if this map contains a mapping for the specified key. boolean containsValue(Object value) Returns true if this map maps one or more keys to the specified value. V get(Object key) Returns the value to which the specified key is mapped, or null if this map contains no mapping for the key. V put(K key, V value) Associates the specified value with the specified key in this map V remove(Object key) Removes the mapping for a key from this map if it is present
158.
159. JCF: L'ORDINAMENTO L' ordinamento è supportato in SortedSet e SortedMap – SortedSet è usato tipicamente per elenchi di parole, di iscritti, etc. – SortedMap è usata tipicamente per elenchi telefonici, agende e più in generale quando vi sono chiavi univoche associate a valori ordinati. Ci sono due modi per ordinare oggetti: • l'interfaccia Comparable dichiara il metodo per definire l'ordinamento naturale in senso ascendente • l'interfaccia Comparator (più complessa) dichiara un insieme di metodi che permettono di avere completo controllo sulle politiche di ordinamento degli oggetti.
160. LA CLASSE FACTORY Collections Collections è una classe factory, che comprende • metodi statici per lavorare con collezioni • funzioni che implementano algoritmi utili (in particolare, ordinamento e ricerca binaria ) • sort(List): ordina una lista con l'algoritmo "merge sort" • shuffle(List): permuta casualmente gli elementi della lista • reverse(List): inverte l'ordine degli elementi della lista • fill(List,Object): rimpie la lista col valore dato • copy(List dest,List src): copia la lista sorgente nell'altra • binarySearch(List,Object): cerca l'elemento dato nella lista ordinata fornita, usando un algoritmo di ricerca binaria.
161. JCF "CLASSICA": PROBLEMI Usare il tipo generico Object per definire contenitori generici causa non pochi problemi – equivale ad abolire il controllo di tipo – rende possibili operazioni sintatticamente corrette ma semanticamente errate – determina quindi il rischio di errori a runtime pur a fronte di compilazioni formalmente corrette – la correttezza è affidata a "commenti d'uso!! – rende il linguaggio non "type safe“ • Java 1.5 introduce un nuovo approccio, basato sul concetto di TIPO PARAMETRICO ("generici")
162. GENERICS • È sbagliato abolire il controllo di tipo! • Occorre un altro modo per esprimere genericità, che consenta un controllo di tipo a compile time – type safety: "se si compila, è certamente corretto“ • Java 1.5 introduce i tipi parametrici ("generici") • Il tipo può essere un parametro: – in funzioni statiche, in classi e metodi di classi – notazione <TIPO> • Si possono definire relazioni fra "tipi generici"
163. ESEMPIO Senza Generics List thingList = new ArrayList(); thingList.add( aThing ); Thing t = (Thing) thingList.get( 0 ); thingList.add( notAThing ); Thing t2 = (Thing) thingList.get( 1 ); // exception Con Generics List<Thing> thingList = new ArrayList<Thing>(); thingList.add( aThing ); Thing t = thingList.get( 0 ); // no cast needed thingList.add( notAThing ); // compile error
164.
165.
166.
167. THREAD E PROCESSI Multitasking: la capacità di un computer (S.O.) di eseguire più lavori contemporaneamente. Diversi processi in esecuzione allo stesso tempo. Multithreading: ogni programma può eseguire contemporaneamente diverse sezioni del programma, tali sezioni sono dette percorsi (thread). I thread possono condividere la stessa area dati.
168. THREAD Programma multithread serve per eseguire più task in parallelo. Thread: percorso in esecuzione all’interno di un programma. Il Sistema Operativo coordina l’esecuzione dei thread (scheduling). Ogni thread ha il suo stack e il proprio insieme di registri virtuali.
169. CLASSE Thread Java definisce a livello di linguaggio il funzionamento dei thread. La classe Thread mantiene lo stato del thread, definisce metodi per controllare i thread. Si deve instanziare un oggetto della classe Thread per ogni thread.
170. CICLO DI VITA DI UN THREAD new -> thread allocato in memoria start() -> il thread diventa running stop() -> il thread è terminato (o fine run()) suspend(), sleep(), wait() -> il thread è bloccato resume(), notify() -> il thread è pronto per ripartire.
171. CREARE UN THREAD Definire una sottoclasse della classe Thread. Overriding del metodo run() Creare un’istanza della sottoclasse prima definita. Invocare il metodo start() dell’istanza creata.
172. INTERFACCIA Runnable Serve per rendere thread istanze di una classe che non deriva dalla classe Thread. Per lanciare un thread di una classe che implementa Runnable devo creare un nuovo oggetto Thread passandogli come argomento il mio oggetto Runnable class MyClass implements Runnable … Thread t1=new Thread(new Myclass()); t1.start() Il costruttore Thread (Runnable r). Invocare start() di Thread per chiamare il nostro run().
173. CONTROLLO DI UN THREAD Il metodo suspend() serve a bloccare l’esecuzione di un thread. Il metodo resume() serve a far riprendere l’esecuzione di un thread. Il metodo sleep(long millis) serve ad interrompere l’esecuzione di un thread per un determinato intervallo di tempo. Il metodo join() attende la fine del thread. Il metodo isAlive() testa se il thread non è terminato. isAlive().
174. PROBLEMI DEI THREAD Accesso a risorse condivise (thread unsafe/safe). Monitor: oggetto che applica il principio della mutua esclusione. Modificatore synchronized per i metodi: su un oggetto il metodo può essere invocato da un solo thread alla volta. Lo statement synchronized, ad esempio per un array, che non ha metodi. Synchronized (expression) Statement Java non gestisce i deadlock.
175. SINCRONIZZAZIONE I monitor (synchronized) possono anche servire per coordinare il funzionamento dei thread. Il metodo wait() , della classe Object, permette ad un oggetto di rilasciare il monitor e di mettersi in attesa di una notifica. Il metodo notifyall() , della classe Object, permette ad un oggetto di notificare a tutti i thread che si sono messi in attesa che possono riprendere l’esecuzione.