vuoi
o PayPal
tutte le volte che vuoi
N.B: una classe annidata NON static non può definire membri non final
static
Classi Local
Varianti di classi annidate che si trovano dentro un blocco di codice (ad esempio un metodo). sono simili alle
classi inner non statiche ed hanno accesso alle variabili definite nel blocco che le contiene ma solo a quelle
definite final 4
Classi Anonime
è una classe “locale” senza un nome assegnato definita e istanziata un’unica volta attraverso una singola
espressione, Per le classi anonime valgono sostanzialmente le medesime regole delle classi locali per quanto
riguarda l’accesso alle variabili locali. Sono usate per:
quando si vuole creare l’istanza di una classe sovrascrivendo alcuni metodi:
class A{
public void methodA() {
System.out.println("methodA");
}
}
class B{
A a = new A() {
public void methodA() {
System.out.println("anonymous methodA");
quando si vuole l’istanza di un’interfaccia:
interface interfaceA{
public void methodA();
}
class B{
interfaceA a = new interfaceA() {
public void methodA() {
System.out.println("anonymous methodA implementer");
Per passarle come argomento a un metodo:
interface Foo {
void methodFoo();
}
class B{
void do(Foo f) { }
}
class A{
void methodA() {
B b = new B();
b.do(new Foo() {
public void methodFoo() {
System.out.println("methodFoo"); 5
Classi Astratte
Hanno metodi astratti (senza body) ed eventualmente può implementare anche metodi concreti. Una classe astratta
è una classe non instanziabile che fornisce una base di metodi astratti che dovranno essere implementati nelle
sottoclassi.
Differenza tra Classi astratte e Interfacce
le classi astratte implementano l’astrazione opzionale (0-100%), le interfacce sono al 100% astrazioni.
Le interfacce supportano l’ereditarietà (posso implementare più interfacce) multipla le classi astratte no
Le interfacce possono avere solo variabili final static
Le classi astratte possono opzionalmente fornire l’implementazione di un’interfaccia (o lasciarla
implementare alle sottoclassi della classe astratta)
Interfacce
Sono classi astratte che consentono a più classi di fornire un insieme di metodi comuni, specificandone solo il
comportamento esterno mentre l’implementazione è indefinita. L’interfaccia è una promessa che la classe
implementerà i metodi dell’interfaccia
public interface FunctionalInterface {
//metodo astratto
public void stampa();
// Default: un metodo che puo' essere sovrascritto
public default void arrivederci() {
System.out.println("arrivederci!");
}
// Static: un metodo che non puo' essere sovrascritto e si chiama col nome
dell'interfaccia
public static void buonPomeriggio() {
System.out.println("buon pomeriggio...");
}
} i metodi dichiarati in un’interfaccia sono implicitamente public abstract
le variabili sono implicitamente public static final
Un metodo deve essere avere un body e quando si implementa l’interfaccia non è possibile
static
sovrascriverlo e può essere chiamato dalla classe che implementa l’interfaccia con:
<nomeInterfaccia>.metodo()
Un metodo consiste in un metodo con un body che viene ereditato automaticamente implementando
default
l’interfaccia, ma è possibile sovrascriverlo.
Interfaccia Funzionale
L’interfaccia funzionale è un particolare tipo di interfaccia poiché ha un solo metodo astratto, è chiamata così
perché è simile ad una funzione matematica 6
Differenza tra static e default nell'interfaccia funzionale
Partendo dal presupposto che l’interfaccia funzionale per definizione ha un metodo astratto. L’aggiunta di metodi
default permette di chiamarli dalla reference dell’interfaccia funzionale. I metodi possono essere chiamati
static
solo con <NomeInterfacciaFunzionale>.metodo()
Lambda Expression
sono espressioni che hanno una notazione molto compatta, e si possono assegnare a riferimenti di interfacce
funzionali.
Runnable r = (<parametri metodo interfaccia funzionale>) -> {<codice del metodo>};
r.run();
tale notazione equivale a creare una nuova classe che implementa l’interfaccia .
Runnable
Creare un oggetto della stessa classe di un oggetto creato con la
lambda
Runnable r1 = () -> { System.out.println("sto runnando"); };
Runnable r2 = new Runnable() {
@Override
public void run() { System.out.println("sto runnando"); }
}; Eccezioni
È una classe le cui istanze segnalano una condizione che impedisce la normale prosecuzione del programma.
Alcune classi sono:
→ accesso oltre i limiti di un array
ArrayIndexOutOfBoundsException
→ divisione per zero
ArithmeticException
→ errore formato numero
NumberFormatException
→ errore input/output
IOException
IllegalArgumentException
Per creare un’eccezione personalizzata si crea una nuova classe col nome che si vuole dare all’eccezione che
estende Exception. Per lanciare un’eccezione dentro un metodo si dichiara:
<metodo>(<parametri>) throws <Eccezione>{
If (…) throw new <Eccezione>();
} 7
Enumerazioni
può essere semplicemente pensato come un modo per vincolare una variabile a poter assumere solo un
determinato set di valori per comodità (ad esempio i giorni della settimana). Utile per i case-switch statement, c
public enum Giorno {LUNEDI, MARTEDI, MERCOLEDI, GIOVEDI, VENERDI, SABATO, DOMENICA}
Giorno giornoDellaSettimana = Giorno.VENERDI;
Giorno giornoConMetodo = Giorno.valueOf(“VENERDI”);
String[] Giorni = Giorno.values(); //array di tutti i giorni come stringhe
Le enumerazioni sono classi, e possono dunque implementare
Metodi
Attributi (meglio se privati)
Costruttori(privati)
Ogni elemento dell’enum viene passato al costruttore privato del metodo per essere inizializzato quindi se
abbiamo un enum:
public enum Elemento {
IDROGENO("H", 1, 1.008),
ELIO("He", 2, 4.003),
// ... altri elementi
LITIO("Li", 3, 6.491);
Il costruttore dovrà essere:
private Elemento(String simbolo, int numeroAtomico, double massaAtomica) {
this.simbolo = simbolo;
this.numeroAtomico = numeroAtomico;
this.massaAtomica = massaAtomica;
}
Con dei metodi publici per fare il get degli attributi di ogni singolo elemento
Static
Un membro è un membro (metodo o variabile) che non è associato con una particolare istanza di una
static
classe ma appartiene alla classe stessa, quindi è accessibile senza aver creato prima istanze della classe. Le classi
non possono essere static a meno che non siano classi innestate. Il metodo statico più conosciuto è:
public static void main(String[] args)
Package & modificatori di accesso
Un package è uno strumento per raggruppare tipi (classi, interfacce, enumerazioni) in qualche modo legati tra
loro, organizzandoli in “gruppi” inserendo package <nomePackage> in testa al file della classe Solitamente,
aziende, associazioni o gruppi che hanno un dominio web, utilizzano come package name proprio il loro dominio
ribaltato; per esempio se il dominio è prova.com il package name potrebbe essere com.prova.mypackage.
public // consente l’accesso a tutto il progetto
protected // accessibile da stesso package o sottoclasse
default // accessibile da stesso package
private // accessibile solo dalla classe stessa 8
Thread
È la più piccola unità di elaborazione indipendente di un programma, quando si lancia un programma dal main ad
esempio, si attiva il main thread.
l'uso di più thread di esecuzione è conveniente e a volte indispensabile. In particolare in un’applicazione con GUI
(per mantenerne la reattività). In una macchina monoprocessore, ogni thread si alterna con gli altri, mentre in una
macchina multiprocessore, più thread possono essere in esecuzione parallelamente. Questo rende la
programmazione multi-thread più complicata.
Avviare un Thread in Java
possiamo creare esplicitamente un thread tramite la classe Thread in java.lang preferibilmente usando
il costruttore: 1
Thread(Runnable <oggettoCheImplementaRunnable>)
Per farlo partire si utilizza il metodo (che può essere evocato una sola volta):
2
.start()
Un thread termina non appena termina l'esecuzione del
run() #definito nel suo oggetto Runnable
si può chiedere la terminazione del Thread invocando il metodo
void interrupt()
Il task eseguito dal thread può usare il seguente metodo che returna un booleano per sapere se c'è
una richiesta di interruzione del thread ed agire di conseguenza.
Thread.currentThread().isInterrupted()
Oppure se si vuole resettare a false la richiesta di interruzione dopo il caso sia verificata:
Thread.interrupted()
1 L'interfaccia funzionale ha il solo metodo che serve proprio a definire
Runnable void run()
un metodo che esegue un programma o task in un qualche thread di esecuzione
2 ritorna immediatamente, non attende che l'esecuzione di nel nuovo thread
start() run()
abbia termine. 9
Sincronizzazione
3
Strategie per la programmazione parallela che rispettino il thread safety :
Confinamento evitare che un dato sia condiviso da più thread.
Immutabilità Cercare quando è possibile di far sì che un dato condiviso sia immutabile ( )
final
Esistono istruzioni come la somma di una variabile che non sono
Sincronizzazione (lock/mutex)
atomiche (ricorda Mips…) per cui se più thread agiscono su una variabile esterna, il risultato potrebbe
non essere consistente, per questo si usa il modificatore di metodo:
4
Synchronized <metodo>{}
Oppure istanziando Object lockN = new Object();
Synchronized (lockN){}
Si possono sincronizzare sia metodi statici che metodi dell'oggetto, è equivalente
a ottenere un lock/mutex sull'oggetto obj, ovvero se un thread accede a un metodo synchronized di un obj, nessun
altro thread può accedere al metodo finché non finisce o il thread va in wait().
È possibile anche usare variabili atomiche con e il suo metodo che in modo
AtomicInteger int getAndIncrement()
atomico incrementa il valore e ritorna il valore prima dell'incremento.
Per motivi di ottimizzazione due thread possono vedere due versioni diverse della stessa variabile (ricorda la
cache L1 di architetture…) se questo è un problema è necessario usare la keyword
Volatile <v