Documenti di Didattica
Documenti di Professioni
Documenti di Cultura
DEFINIZIONI:
¾ Classe: è un modello informatico usato per creare degli oggetti con
caratteristiche simili. La classe è un͛astrazione che descrive le proprietà di oggetti
caratterizzati da stesse operazioni, stessa scrittura interna e stesso
comportamento e che consente la creazione di istanze
¾ Istanza: è un elemento concreto di una classe
¾ New: operatore usato per creare delle istanze. Invoca un costruttore della classe
passando eventualmente dei parametri
¾ Attributo costante: si tratta di un attributo che è predefinito, non cambia
¾ Attributo: variabile globale con valore variabile
¾ Metodi costruttori: metodo che assegna agli attributi dei valori e hanno lo stesso
nome della classe
¾ Identificatori: sono i nomi che vengono dati alle classi, agli attributi, alle variabili
¾ Commento: è una parte di file che, preceduta da ͞//͟ oppure ͞/*...*/͟, viene
ignorata dal compilatore
¾ JavaDOC: sistema che automaticamente crea la documentazione del codice; è
possibile generarla tramite un web browser
¾ Tag: parola precedute da @ che indicano a quale specifico aspetto si riferisci il
commento
¾ Incapsulamento: proprietà per cui la struttura interna dell͛oggetto è nascosta
agli altri oggetti
¾ Oggetto: è rappresentato da delle variabili e da un tipo
¾ Editor: Programma che permette di inserire modificare del testo
¾ Coesione: misura che indica quanto strettamente correlato siano le diverse
funzionalità di una classe; più una classe ha responsabilità ad un solo compito
maggiore sarà la sua coesione
¾ Accoppiamento: fa riferimento ai legami che ci sono tra le classi; se due classi
dipendono strettamente l͛una dall͛altra allora avremo un alto accoppiamento
¾ Modularità: indica che le classi sono i moduli del sistema software
¾ Riuso: tramite l͛ereditarietà posso riusare la definizione di una classe per definire
delle nuove sottoclassi
¾ Information hiding: strutture dati e algoritmi possono essere nascosti alla
visibilità esterna all͛oggetto
¾ Estendibilità: ereditarietà, polimorfismo e binding dinamico favoriscono
l͛aggiunta di nuove funzionalità minimizzando le modifiche
¾ Tipo di dato: rappresentazione concreta di un concetto
¾ Interfaccia: parte visibile di una classe; è il ͞contratto͟ tra chi sviluppa e chi usa la
classe
¾ Raffinamento: modificare in qualche modo le proprietà ereditate
¾ Estensione: aggiungere nuove proprietà rispetto a quelle ereditate
¾ Final: indica una definizione definitiva
¾ Eccezione: sitazione che impedisce la regolamentare funzione del programma
¾ Asserzione: condizione booleana che il programmatore ritiene debba essere vera
in qualsiasi momento in una specifica posizione del programma; se l'espressione
è vera l'asserzione conferma le aspettative del programmatore sul buon
funzionamento del codice, se è falsa viene lanciata l'eccezione AssertionError
¾ Ricorsione: la definizione di un͛entità contiene un riferimento all͛entità stessa
¾ Strutture dati: tipi di dati astratti per i quali sono definiti metodi standard
¾ Genericità: deve essere possibile definire classi generiche con capacità universali
o comunque riferite ad un ampio insieme di classi
¾ Type safety: nell͛ambito di classi generiche si vogliono evitare mescolanze
indesiderate di tipi
CONCETTI:
PDF: primi passi
La realizzazione di un programma prevede diversi step:
1. Analisi del problema da risolvere
2. Progettare l͛algoritmo per risolvere il problema
3. Codificare le strutture e gli algoritmi in linguaggio di programmazione
4. Documentare il codice
5. Verificare la validità del codice
6. Fare la manutenzione del codice
JAVA
Java è un linguaggio di programmazione che offre un insieme di piattaforme e
tecnologie con strumenti che permettono l'utilizzo di programmi scritti in Java in
diverse situazioni.
La Java SE (Standard Edition) è una piattaforma base destinata alla realizzazione di
applicazioni su calcolatori convenzionali.
Java si compone di due elementi principali:
1. JRE (Java Runtime Environment): contiene strumenti per l'esecuzione di
programmi Java già sviluppati
2. JDK (Java Development Kit): contiene strumenti per lo sviluppo di
programmi
Le due caratteristiche principali del linguaggio Java sono la sicurezza e la portabilità.
In Java il file dovrà chiamarsi nome-del-file. java (produzione del codice sorgente)
per poter funzionare. Successivamente ci dovrà essere la compilazione del codice
sorgente cioè la produzione del bytecode quindi un file.class. Infine, avremo
l'esecuzione cioè l'interpretazione del bytecode da parte di un'interprete software
che in questo caso è la JVM (Java Virtual Machine), la quale prende i file, li unisce e
viene eseguito il programma.
Java è definito un linguaggio case sensitive questo significa che anche il
cambiamento di un singolo carattere implica un cambiamento.
Una cosa utile da saper fare è quella di imparare quali sono gli errori più comuni ed
evitarli; per far ciò si possono usare delle strategie di programmazione difensiva per
ridurre la probabilità d'errore.
In Java esistono principalmente due tipi di errori:
Come in C anche in Java si dichiarano delle classi ma in Java non esistono le struct. In
Java la classe si indica con la parola class. Le classi sono composte da attributi e
metodi; entrambi possono essere accessibili diversamente dai vari membri:
x private: accessibile solo all'interno della classe
x friendly (accesso di default)
x protected: accessibile dalle sottoclassi
x public: libero accesso
La differenza sostanziale tra classe e struttura è che i membri di una struttura sono
di default pubblici mentre quelli di una classe sono, per default, a livello di
pacchetto.
ї questo significa che l͛istanza di una classe è visibile all͛interno del proprio ambito
ma i suoi membri protetti (private) no; infatti, una classe ͞esterna͟ non può
accedere direttamente ai membri protetti della classe
I metodi definiscono il comportamento degli oggetti di quella classe; il
comportamento prevede azioni del tipo:
x accesso ai data member dell͛oggetto
x aggiornamento dei data member
x test dei data member
x visualizzazione dei data member
A livello lavorativo quando si realizza un programma da consegnare ad un cliente
bisogna cerare di ridurre i tempi di realizzazione, aumentare la produttività e la
qualità. Lo sviluppo del programma deve essere realizzato in via incrementale
tramite dei release piccoli e frequenti; il coinvolgimento del cliente è fondamentale.
Nella metodologia ĚĞůů͛džƚƌĞŵĞ Programming ci sono diverse regole suddivise in
quattro macroaree:
L͛UML è un tipo di linguaggio che tramite una serie di diagrammi e frecce ci consente
di rappresentare ͞graficamente͟ la realizzazione dell͛algoritmo risolutivo di un
problema.
ї Diagramma delle classi: rappresenta le classi che fanno parte del sistema e le
relazioni tra di esse. Nel diagramma delle classi sono presenti delle strutture per
rappresentare le varie relazioni
Î Ereditarietà
Î Associazione: individua una connessione logica tra classi
Î Cardinalità: indica il numero di istanze di una classe che possono essere
associate ad una singola istanza dell'altra classe
Î Molteplicità: numero di oggetti che partecipano all'associazione
Î Aggregazione: esprime il concetto ͞ è parte di ͞
Î Composizione: è un caso particolare di aggregazione dove la distruzione
dell'oggetto principale provoca la distruzione anche di quelle secondarie
Î Dipendenza: indica che un oggetto può chiamare i metodi di un altro
senza possedere un'istanza
Cosa posso fare con le istanze: le principali operazioni che si possono effettuare
sulle variabili che fanno riferimento a distanze sono:
Come uso i metodi: la documentazione delle varie classi contiene l'elenco dei
metodi disponibili ma il grande numero di classi e metodi che Java ci mette a
disposizione a volte rende difficile trovare ciò che si necessita. Una prima
soluzione è l'utilizzo di Internet ma se quest'ultimo non ci dà la risposta
desiderata bisogna trovare il package, individuare la classe e successivamente
il metodo
L'utente desidera anche avere una visualizzazione comoda dei dati in output. Con
comoda si intende per esempio che la stampa di numeri double non abbia infinite
cifre dopo la virgola oppure che diversi risultati vengono stampati su diverse righe
invece che su una unica.
Î System.out è l'oggetto che stampa a video. Se vengono richiamati i
metodi
.print o .println ciò che viene stampato a video è il valore di qualunque
variabile in maniera abbastanza grezza; per rendere più presentabile la
stampa si può invocare il metodo .printf: il primo argomento è una stringa e
fornisce dettagli su ciò che deve essere stampato usando gli opportuni
specificatori, gli argomenti successivi al primo corrispondono ai valori che
devono essere sostituiti al posto degli specificatori nella stampa prodotta
È possibile produrre oggetti stringa con contenuto formattato; questo compito è
svolto da un metodo static della classe String denominato format che riceve
argomenti nello stesso modo di printf
Un altro modo per ottenere un buon output è quello della scrittura su un file di
testo. Per scrivere su un file è necessario creare un oggetto di tipo PrintWriter; se il
file già esiste, questo verrà svuotato poi si scriverà all͛interno; se il file non esiste ne
verrà creato uno vuoto. Verranno utilizzati i metodi print e println per scrivere
l'oggetto sul file e al termine delle operazioni sarà necessario chiudere il file con il
comando out.close().
Sono possibili delle omonimie tra attributi e variabili affinché essi siano definiti a
livelli diversi. Tuttavia, l͛omonimia deve essere evitata in generale. All'interno del
costruttore è naturale che i nomi siano simili a quelli degli attributi, per risolvere
questo problema si può passare all'utilizzo dell'underscore oppure del termine this.
Variabili, espressioni e invocazioni e tipi di metodi hanno tutti un tipo specificato
nella definizione. Java è un linguaggio che effettua controlli severi sull'utilizzo
corretto dei tipi di dato:
x l'assegnazione deve essere fatta tra tipi compatibili
x gli argomenti passati ad un metodo devono essere compatibili a quelli
specificati nella lista di argomenti
x la parola return deve essere seguita da un tipo uguale a quello
specificato nella definizione del metodo
Collection: gli array sono adatti solo quando la struttura dati collettiva non
deve variare dinamicamente la sua dimensione; infatti, la dimensione di un
array viene fissata nel momento della sua creazione. le collection si formano
di diverse classi, tra cui la più importante è la famiglia List. In questa classe si
possono riconoscere tre classi principali: Vector, ArrayList e LinkedList.
o ArrayList: Funziona in maniera simile a quella degli array. Possiamo
avere ArrayList di tipo elementare (da usare con la classe wrapper)
oppure di tipo strutturato. Inizialmente una variabile ArrayList viene
costruita come contenitore vuoto, gli elementi vengono costruiti in
seguito. Operazioni comuni:
aggiungere elementi: tramite il metodo .add si aggiunge un
nuovo elemento in coda. L'elemento aggiunto deve essere di tipo
uguale a quelli già esistenti. Se si vuole aggiungere un elemento
in testa ad una realista bisogna usare un'altra versione del
metodo add cioè add(0, noemVariabile)
accedere agli elementi: Tramite il metodo .get ricevo l'elemento
dell'ArrayList in una determinata posizione
rimuovere un elemento: tramite il metodo .remove
verificare la lunghezza di un ArrayList: tramite il metodo .size
impostare un elemento: tramite il metodo .set imposto un
elemento ad un nuovo valore
azzerare i valori: per ogni elemento impongo che l͛i-esimo
elemento sia pari a 0
PDF: ereditarietà
La derivazione tra classi è uno degli strumenti più utili dell͛approccio alla
programmazione a oggetti. Una classe può essere definita come derivazione di
un͛altra. La classe derivata viene chiamata figlia, mentre quella da cui deriva è
chiamata classe base. La classe base in Java è unica: la classe Object. La relazione di
derivazione da un luogo a un albero di classi la cui radice è la classe Object.
L͛ereditarietà è dunque il meccanismo di trasmissione delle proprietà dalle
superclassi alle sottoclassi. Vengono ereditati i metodi public e protected, su
ereditano anche i metodi friendly se la sottoclasse è definita nello stesso package,
mentre gli attributi vengono ereditati tutti tenendo però in considerazione le regole
dei loro modificatori d'accesso
ї Operatore instanceof: è un operatore booleano che restituisce true se l'oggetto è
un'istanza diretta di una superclasse o di una sua classe derivata (nome-oggetto
instanceof nome-classe).
Per quanto riguarda l'assegnamento, a una variabile di una sottoclasse si può
assegnare una variabile di una superclasse a patto di fare un cast esplicito; ha una
variabile di una superclasse si può assegnare un valore di una qualunque
sottoclasse.
vado ad utilizzare il meccanismo di ereditarietà solo se tra due classi esiste una
relazione ͞is-a͟ cioè se ogni oggetto della sottoclasse è anche un oggetto della
superclasse. La definizione di una nuova classe può specializzare quella della classe
base in due direzioni: estensione e raffinamento
ESTENSIONE SUGLI ATTRIBUTI: la classe derivata può definire attributi che
non erano presenti nella superclasse; quindi, ogni oggetto della classe
derivata presenta degli attributi della superclasse e quelli eventualmente
appena definiti
RAFFINAMENTO SUGLI ATTRIBUTI: è possibile definire attributi con lo stesso
nome di attributi ereditati ma questo non significa che il nuovo attributo
elimina l͛ereditato, lo rende solo invisibile (processo di shadowing)
ESTENSIONE SUI METODI: si possono aggiungere nuovi metodi specifici
oppure fare l͛overloading dei metodi ereditati. Definire una nuova forma per
un metodo ereditato è ƵŶ͛ĞƐƚĞŶƐŝŽŶĞ͕ŝŶĨĂƚƚŝ͕ i metodi ereditati con lista di
argomenti diversi continuano ad essere visibili separatamente. La selezione
del metodo avverrà in base agli argomenti che verranno passati
RAFFINAMENTO SUI METODI: consiste nel fare l'overriding dei metodi
ereditati cioè andare a creare una nuova versione di un metodo ereditato con
lista degli argomenti uguale a quella di una delle versioni ereditate. la nuova
versione maschera quella precedente. L͛overriding dei metodi è spesso utile
quando bisogna ridefinire i metodi ereditati dalla classe Object, in particolare
è molto comune ridefinire il metodo toString() o il metodo equals().
o toString(): ritorna una stringa
o equals(): controlla se due riferimenti riferiscono esattamente lo stesso
oggetto
Overloading vs Overriding: i metodi overloaded sono tutti gli effetti metodi
diversi, hanno in comune solo il nome. I metodi overridden sono ridefinizioni
di un metodo già esistente: tra loro esiste la relazione di mascheramento.
L͛overriding, in particolare, permette di ridefinire e specializzare metodi
definiti in una superclasse. Con questi metodi è comunque possibile invocare
il metodo nella versione della superclasse utilizzando la parola chiave super
seguita dal nome del metodo della superclasse. Il termine super isolato serve
per invocare il costruttore della superclasse da dentro il costruttore della
sottoclasse e deve essere la prima istruzione del costruttore.
COSTRUZIONE DI UN͛ISTANZA
In virtù del meccanismo di ereditarietà è necessario sottolineare che la costruzione
di un'istanza di una classe non coinvolge solo la classe stessa ma anche le sue
superclassi. Riconosciamo dunque due fasi per la costruzione di un'istanza:
1. Fase precedente: la costruzione di un͛istanza è preceduta dal caricamento di
tutte le superclassi e dall͛inizializzazioni delle loro variabili static
2. Fase successiva: assegnazione dei valori di default agli attributi, chiamata al
costruttore della superclasse, esecuzione di inizializzazione esplicita degli
attributi e, infine, esecuzione del corpo del costruttore
Nel caso di metodi overloaded la selezione del metodo da eseguire è implicita nella
chiamata e si fa al momento della compilazione; nel caso di metodi overriden la
selezione dipende dall'oggetto al quale è riferita l'invocazione, per questo motivo la
selezione deve essere effettuata durante l'esecuzione (processo di late binding).
Il polimorfismo invece permette di scrivere codice generico che si adatta
automaticamente a tutte le specializzazioni di una certa classe; il trucco è la
selezione del metodo sulla base dell'oggetto durante l'esecuzione. Il polimorfismo
permette di creare nuove classi derivate senza cambiare nulla nel codice delle classi
che usano le loro super classi ed è inoltre predisposto per un riuso automatico
Per bloccare questo rapporto tra classe e sottoclasse esiste la parola chiave final:
9 attributo final è una costante
9 metodo Final non può essere overridden
9 classe Final non può avere sottoclassi
Metodi e classi final servono ad aumentare l'efficienza
CLASSI ASTRATTE
Con metodo astratto si intende un metodo privo di implementazione che è
preceduto dalla parola chiave abstract. Una classe può essere definita astratta anche
se non ha dei metodi astratti e, in particolare, non può avere istanze dirette ma solo
sottoclassi. Variabili di una classe astratta sono ammesse solo se contengono
riferimenti a istanze di sottoclasse
INTERFACE
Java non permette l'eredità da più classi ma il concetto di eredità multipla è utile: ci
viene messo a disposizione la cosiddetta Interface. quest'ultima è una sorta di classe
astratta ancora più astratta e una classe in grado di implementare un numero
arbitrario di interfacce. gli attributi solitamente sono static e final mentre i metodi
sono abstract e public. L'utilizzo della parola riservata implements serve per indicare
che una classe implementa un'interfaccia.
Si possono implementare quante interfacce si vuole; se una classe implementa un
Interface deve fornire un'implementazione per tutti i metodi da essere specificati. A
sua volta un'interfaccia può ereditare da un'altra tramite la voce extends e quindi
aggiungere nuovi metodi. Come una classe astratta, un'interfaccia non può avere
istanze ma sono ammessi solo riferimenti a istanze di classi che le implementano.
Un nome di Interface può comparire come tipo dei dato. Le interfacce permettono
di specificare comportamenti standardizzati senza sottolineare come essi vengono
realizzati all'interno di una classe
CLASSI INTERNE
Si tratta di una classe definita all͛interno di un͛altra classe o di un metodo. Le classi
interne sono utili per classi di piccole dimensioni e i loro metodi possono accedere a
variabili locali definite solo nel metodo
PDF: eccezioni
L'esecuzione di certe istruzioni può generare eccezioni. In particolare, un'eccezione
viene creata quando un oggetto appartenente ad una certa classe viene creato a
seguito di un'anomalia; questo oggetto contiene informazioni su cosa è successo e
viene catturato e utilizzato dal codice per la gestione delle eccezioni. Gli scopi della
gestione delle eccezioni sono tre:
1. evitare numerosi controlli ripetuti
2. tenere distinti codice normale e codice di gestione anomalie
3. tener conto dell'anomalia in maniera appropriata
Formule di gestione delle eccezioni:
Try-catch: nel blocco try sono contenute le istruzioni che potrebbero generare
delle eccezioni, nel blocco catch è contenuto il codice di gestione in caso di
eccezione; è facoltativo specificare più catch
I metodi nextQualcosa() della classe scanner possono dar luogo a tre tipi di
eccezione
o InputMismatchException se il dato non è nel formato appropriato
o NoSuchElementException Se non ci sono dati
o IllegalStateException se l'istanza di Scanner non è in grado di fornire dati
Throws e throw: nella definizione dei metodi è possibile che si verificano
condizioni anomale che generano eccezioni. Ad esempio, il metodo della
radice quadrata del classe Math qualora venga invocato su un parametro
minore di zero genera l'eccezione Not a Number. La parola throws viene posta
dopo la lista degli argomenti di un metodo e definisce quali tipi di eccezione il
metodo può generare; la parola throw all'interno del codice di un metodo
determina l'uscita del metodo lanciando un'eccezione, deve essere seguita dal
riferimento ad un oggetto eccezione creato seguito di un'anomalia.
Finally: contiene codice che viene eseguito in ogni caso o dopo il
completamento corretto del blocco try oppure dopo che è stata generata
un'eccezione gestita nel blocco catch
Le eccezioni si dividono in tre categorie:
- controllo obbligatorio: eccezioni che è obbligatorio dichiarare e gestire
altrimenti sia un errore di compilazione
- controllo non obbligatorio: eccezioni che è facoltativo dichiarare gestire; sono
sottoclassi della classe RunTimeException
- errori interni: segnalati da sottoclassi di Error che non sono gestibili (es:
OutOfMemoryError)
file. Infatti, la chiusura fa sì che il sistema liberi la risorsa utilizzata per connettere il
file allo Stream e svolga operazioni di pulizia; se mancasse la chiusura Java la
farebbe in automatico al termine dell'esecuzione del programma ma se quest'ultimo
termina inaspettatamente Java potrebbe non riuscire a fare in tempo a scrivere tutti
i dati sul file di Stream
Î Quando il file di input/output non esiste viene lanciata un'eccezione
chiamata FileNotFoundException che viene gestita con un blocco try-catch
oppure throws
STREAM DI TESTO
I file di testo contengono solo caratteri rappresentati secondo standard
universalmente adottati
- sono intellegibili e apribili con qualunque editor
- possono essere utilizzati da altri programmi
Hanno però di negativo che occupano più spazio e per trattare i numeri come
numeri bisogna convertirli dalla rappresentazione testuale a quella numerica.
Per gli Stream di testo si fa riferimento alle classi Reader e Writer che forniscono le
basi per scrivere un carattere alla volta. La classe PrintWriter offre la possibilità di
invocare i metodi print, println e printf per la stampa di oggetti. La classe FileWriter
offre un costruttore di append mode.
Per quanto riguarda la lettura non esiste un metodo di lettura universale; in via
normale si leggono stringhe poi si converte il tutto usando dei metodi appositi (nel
caso dei tipi elementari sono quelli della classe wrapper). È possibile creare
un'istanza di Scanner associato ad uno Stream di lettura di testo; questo permette di
leggere e convertire simultaneamente la rappresentazione testuale di un numero
usando metodi come nextInt, nextDouble. Come già sappiamo la classe Scanner
permette di acquisire valori da InputStream in maniera molto più comoda.
Il modo più semplice per leggere del testo è utilizzare la classe Scanner; per leggere
da un file creiamo un Filereader che andremo ad utilizzare per creare l'oggetto
Scanner; dopodiché, potremo utilizzare i metodi della classe Scanner per leggere i
dati del file. Per quanto riguarda la scrittura su un file, invece, creeremo un oggetto
PrintWriter; se il file già esiste questo viene svuotato altrimenti viene creato un file
vuoto; successivamente possiamo passare all'utilizzo di print e println per scrivere
sul PrintWriter
STREAM DI OGGETTI
Un programma Java rappresenta i suoi dati più importanti come oggetti, quindi,
nasce la necessità di salvare su file direttamente gli oggetti. Java offre un modo
comodo per salvare leggere oggetti e i loro collegati tramite gli Object Stream, in
particolare con i metodi writeObject e readObject. Il metodo di lettura restituisce un
riferimento ad un oggetto generico ed è quindi richiesto un cast esplicito per
riattribuire all'oggetto il suo tipo originario. Per poter utilizzare gli Object Stream
una classe deve implementare Serializable. Automaticamente le viene aggiunto un
attributo di tipo long denominato serialVersionUID che rappresenta il numero di
versione della classe e viene memorizzato al momento della scrittura delle sue
istanze tramite writeObject. Ogni volta che il codice sorgente della classe cambia
varia anche il valore di questo attributo; se si tenta di leggere da un file degli oggetti
salvati con numero di serie precedente a quella attuale si lancia un'eccezione.
A volte non si vuole che alcuni dati vengano salvati come valori che sono stati
memorizzati per velocizzare il codice oppure password e dati segreti. Java per
aiutarci fornisce la keyword transient.
Classe sia serializzabile, devono essere verificate le seguenti condizioni
- la classe implementa l'interfaccia Serializable
- tutte le variabili istanze di tipo classe sono istanze di classi serializzabili
- la superclasse diretta della classe è serializzabile o definisce un costruttore di
default
FILE AD ACCESSO DIRETTO
I file ad accesso diretto sono realizzati tramite la classe RandomAccessFile che
implementa le interfacce DataInput e DataOutput
STREAM CON COMPRESSIONE DATI
Classi Zip Stream e GZIP Stream supporto nell'attività di compressione o
decompressione negli Stream. i costruttori hanno sempre come parametro un
InputStream o OutputStream
PDF: ricorsione
Per essere corretta dal punto di vista logico, la definizione ricorsiva deve presentare
diverse alternative, tra le quali almeno una non deve contenere l'autoriferimento.
Possiamo riconoscere due grandi strutture dati ricorsive:
Î lista: vuota oppure Costituita dal primo elemento della lista e da
un'altra lista
Î albero: singolo nodo oppure insieme costituito da un singolo nodo e da
altri alberi
I metodi ricorsivi sono dei metodi che si vanno ad invocare all'interno del metodo
stesso. Affinché la definizione ricorsiva sia corretta è necessario che:
- sia presente una condizione di terminazione
- ad ogni chiamata ricorsiva si effettua un passo di ricorsione, cioè ci si avvicina
sempre di più alla condizione di terminazione
Ricorsione e iterazione rappresentano due scelte alternative per risolvere i problemi
che richiedono l'esecuzione ripetuta di certe operazioni: la ricorsione privilegia la
semplicità di codifica mentre l'interazione privilegia l'efficienza di esecuzione.
È preferibile l'uso dell'iterazione quando la soluzione iterativa e ricorsiva è
paragonabile dal punto di vista della complessità e l'occupazione di memoria
generata dalla ricorsione viene evitata tramite la soluzione iterativa. È preferibile
l'uso della ricorsione quando la complessità della soluzione iterativa è decisamente
superiore a quella ricorsiva e l'occupazione di memoria è necessaria alla soluzione
del problema e si verificherebbe anche nella soluzione iterativa
ArrayList Vector
fornisce tre metodi di natura accessoria ha svariati metodi
più efficiente meno efficiente
non è predisposta per la ben predisposto per la programmazione
programmazione multi-thread multi-thread
classe generica non bisogna confondersi tra le variabili di tipo del metodo e le
variabili di tipo dell͛intera classe. Spesso i metodi generici sono static e definiti in
classi non generiche. Per richiamare questi metodi non è necessario specificare la
sostituzione tra parametri di tipo e tipo effettivamente utilizzato, il compilatore
riconosce la sostituzione dal passaggio del parametro. Per i metodi generici non è
possibile utilizzare i tipi primitivi ma, per forza, i tipi della classe wrapper.
Nel caso in cui noi volessimo limitare il nostro parametro di tipo, ed evitare che la
nostra classe abbia valenza universale, possiamo vincolarlo al rispetto di
determinate caratteristiche
9 Vincolo extends: si può imporre al tipo generico di essere derivato da una
certa classe o interface. Il vincolo viene espresso tra le <> usando la parola
chiave extends (es: <T extends Comparable>)
9 Vincolo super: è possibile imporre il vincolo di essere superclasse di un tipo
specificato. Il vincolo è espresso usando la parola chiave super tra <>
9 Carattere wildcard: il carattere ? all͛interno di <> rappresenta il jolly di
qualunque tipo. Esso è utilizzabile in combinazione con i vincoli extends o
super. Usato da solo indica una sostituzione totalmente libera
Un albero binario è un albero con la caratteristica che ogni nodo può avere al
massimo due figli. Essi sono molto utilizzati per la gestione di dati dotati di
ordinamento, in quanto permettono di effettuare operazioni di inserimento e di
ricerca
ESPRESSIONI LAMBDA
L͛espressione lambda è un blocco di codice preceduto dalla specifica delle variabili
che devono essere passare al codice (es: (Parametri) -> {espressione})