Sei sulla pagina 1di 38

lOMoARcPSD|15098180

Riassuno Java Teoria

Informatica (Università degli Studi di Brescia)

StuDocu is not sponsored or endorsed by any college or university


Downloaded by Cheikhouna Thiam (thiamcheikhouna120@gmail.com)
lOMoARcPSD|15098180

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

Downloaded by Cheikhouna Thiam (thiamcheikhouna120@gmail.com)


lOMoARcPSD|15098180

¾ Extreme programming: metodologia di sviluppo software che ͞stimola͟ la


scrittura di codice di qualità e la rapidità di risposta ai cambiamenti di requisiti
¾ Package: sistema utile per contestualizzare il nome di una classe o interfaccia
¾ UML (Unified Modeling Language): è un linguaggio di progettazione che fornisce
una serie di diagrammi per rappresentare l͛idea di realizzazione di un programma
¾ Dati: informazioni di qualche tipo rappresentate in qualche formato
¾ Operazioni: azioni eseguite sui dati per qualche scopo
¾ Static: parola riservata che viene usata per indicare il livello di definizione di un
attributo o di un metodo. Se la parola static è presente l'attributo o il metodo è
definito a livello di classe; se la parola static non è presente l'attributo o il
metodo è definito a livello di istanza. Per accedere a metodi static basta
richiamare il metodo sulla classe stessa
¾ Overloading: definizione di metodi con lo stesso nome ma liste di parametri
diverse
¾ Autoboxing: conversione automatica tra tipi primitivi e le corrispondenti classi
wrapper
¾ Off-bye-one error: errore che avviene quando un ciclo viene eseguito più o meno
volte rispetto al necessario
¾ Metodo: insieme di istruzioni utilizzate per risolvere i problemi scomponendoli in
sotto problemi e per rendere il codice più leggibile
¾ Return: istruzione che causa l͛uscita immediata dal metodo
¾ Lista di argomenti: sequenza di argomenti che rappresentano i dati che il
metodo deve ricevere in ingresso da chi lo invoca; questi dati sono caratterizzati
da nome e tipo (deve essere sempre specificato)
¾ Argomento implicito: variabile sulla quale viene richiamato un metodo non static
¾ This: parola riservata che può essere utilizzata all'interno del corpo di un metodo
per esplicitare il riferimento all'argomento implicito; nel costruttore si riferisce
all'oggetto che si sta costruendo
¾ Variabili locali: variabili visibili dal punto di definizione che muoiono quando
smettono di essere visibili
¾ Garbage Collector: processo che gira in background e si occupa di cercare gli
oggetti inutilizzati e di eliminarli
¾ Variabile elementare: struttura usata per riferire un valore
¾ Espressione: struttura per calcolare un valore; questo valore sarà il risultato della
mia espressione
¾ Metodo con ritorno: metodo non void che viene usato per produrre un risultato
¾ Array: tipo strutturato che rappresenta una sequenza di dimensione prefissata di
elementi dello stesso tipo (semplici o strutturati)

Downloaded by Cheikhouna Thiam (thiamcheikhouna120@gmail.com)


lOMoARcPSD|15098180

¾ 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

Downloaded by Cheikhouna Thiam (thiamcheikhouna120@gmail.com)


lOMoARcPSD|15098180

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:

Downloaded by Cheikhouna Thiam (thiamcheikhouna120@gmail.com)


lOMoARcPSD|15098180

1. Compile-time error: una violazione delle regole del linguaggio di


programmazione
2. Run-time error: un errore che si verifica durante l'esecuzione di un
programma; ho un diverso comportamento del programma rispetto a quello
previsto
Î Logic error: il codice produce un risultato errato
STRUTTURA JAVA
Solitamente un programma Java è costituito da uno o più classi e all'interno delle
classi solitamente sono presenti attributi e metodi
Î Una classe particolare, sempre presente in un programma Java, è la
classe Main che è la classe che contiene il metodo che consente l'esecuzione
del programma
Come abbiamo visto in Java sono presenti dei metodi cioè delle funzioni che
contengono delle determinate operazioni da fare per poter modificare attributi
oppure variabili. I metodi vengono richiamati su determinate variabili di un
determinato tipo e il tutto viene fatto attraverso il punto [es: assistente.saluta();]. La
definizione del metodo è quella stabilita nella classe di cui l'oggetto istanza. Tramite
il metodo costruttore è possibile assegnare dei valori agli attributi.
Riassumendo quindi un programma Java è un programma costituito da almeno una
classe che contiene il metodo main e normalmente da una o più classi. La classe che
contiene il metodo main non contiene di solito molto altro e il suo scopo è quello di
dare l'avvio all'esecuzione; la classe che non contiene il main non è concepita per
essere istanziata; esistono delle classi il cui scopo è quello di rappresentare un
prototipo generico di determinati oggetti che hanno delle caratteristiche simili ma
delle proprietà specifiche diverse. La creazione di nuove istanze viene fatta tramite
l'operatore new; la definizione di una classe specifica le operazioni che possono
essere eseguite dalle istanze della classe stessa. La definizione di una classe
comprende attributi e metodi; se la classe è istanziale tra i metodi sicuramente vi è il
metodo costruttore.

Downloaded by Cheikhouna Thiam (thiamcheikhouna120@gmail.com)


lOMoARcPSD|15098180

PDF: buone abitudini


La professionalità di un programmatore si nota anche dallo stile, infatti delle
mancanze di stile comprendono, errori perdite di tempo inefficienze o brutte figure.
Ci sono delle regole di stile che servono per garantire una facile leggibilità e
comprensibilità del codice:
1. Scelta dei nomi: durante la programmazione fondamentale dare nomi
significativi e autoesplicativi per rendere il codice più chiaro. L'uso di nomi
significativi riduce l'utilizzo dei commenti
Î Identificatori validi:
o inizia per un carattere alfabetico, per underscore oppure carattere
dollaro
o contiene solo caratteri alfabetici, numerici, underscore e dollaro
o è lungo meno di 65535 caratteri
o i nomi delle classi iniziano sempre con la lettera maiuscola
o i nomi di attributi, variabili hanno sempre lettera minuscola iniziale
Î Nomi di costante:
o sono tutti in maiuscolo
o si usa underscore per evidenziare la separazione tra parole
2. Divisone sulle diverse righe: ogni riga contiene una sola istruzione o
definizione ed ogni istruzione o definizione sta su una sola riga
3. Distinzione delle parti: voi le parti logicamente distinte sono spazialmente
separate
4. Parentesi graffe: ogni parentesi graffa aperta è il primo o l'ultimo carattere
della sua riga; ogni parentesi graffa chiusa è preceduta da un ritorno; tutto ciò
che è compreso tra le graffe viene inventato verso destra
Î 3 Stili per le parentesi graffe { }:
o Stile 1: ogni graffa sta isolata su una riga, le graffe corrispondenti
sono allineate in verticale
o Stile 2: voi ogni graffa aperta sta all'inizio di una riga non vuota la
chiusa corrispondente allineate in verticale
o Stile 3: ogni graffa aperta sta alla fine di una riga non vuota,
corrispondente allenata in verticale all'inizio di tale riga
I commenti sono una parte di file che viene ignorata dal compilatore, come se non ci
fossero. I commenti hanno fondamentalmente tre usi:
a. essere letti da altri programmatori per facilitare la comprensione per il
codice
Î consigliato quando si voi realizzano codici particolarmente complessi

Downloaded by Cheikhouna Thiam (thiamcheikhouna120@gmail.com)


lOMoARcPSD|15098180

b. escludere temporaneamente delle parti di codice contenenti errori


Î utile nelle fasi di correzione modifica
c. essere elaborati da programmi diversi dal compilatore (JavaDOC)
Î produrre documentazione di buona qualità
In un programma professionale la presenza di commenti è fondamentale perché la
documentazione descrive classi e metodi e permette la comprensione del codice
realizzato da altri.
L͛organizzazione di un file è fondamentale: ogni classe è contenuta in un file con
estensione .java e nome esattamente uguale a quello della classe.

Downloaded by Cheikhouna Thiam (thiamcheikhouna120@gmail.com)


lOMoARcPSD|15098180

PDF: programmazione orientata agli oggetti


Java è un linguaggio di programmazione orientato agli oggetti.
Î Concetto base: separare i dettagli secondari dell'implementazione dalle
proprietà fondamentali
Esistono due tipologie di programmazione:
1. Programmazione tradizionale (top-down): individuare le funzionalità del
sistema finché ho dei sottoproblemi di complessità accettabile
2. Programmazione orientata agli oggetti (bottom-up): individuare delle entità
astratte (oggetti) facenti parte del sistema, le loro proprietà e interrelazioni
tra loro
Cosa sono gli oggetti? Gli oggetti sono come fornitori di servizi; lo scopo della
programmazione ad oggetti è quello di andare a introdurre un livello di astrazione
per gestire la complessità dei problemi. L͛astrazione può essere fatta su due livelli:
1. Astrazione sui dati: astrarre estrarre gli oggetti
2. Astrazione su un controllo: astrarre una data funzionalità dalla sua
implementazione
In Java il tipo di dato è un insieme di valori che possono assumere un'informazione
(es: variabile), ma voi anche l'insieme di tutte le operazioni possibili su dati di questo
tipo. Infatti, la programmazione ad oggetti consente di manipolare i gruppi di
variabili ed aggregarle in oggetti; in altre parole, la programmazione ad oggetti si
basa sull͛incapsulazione delle variabili all'interno degli oggetti e sulla creazione di
codice che descrive il comportamento di questi oggetti.
Per poter eseguire un buon programma (secondo la programmazione orientata agli
oggetti) devo seguire questa scaletta:
1. Identificare le classi e gli oggetti che descrivono il problema
2. Identificare i dati membro di ciascun oggetto
3. Identificare i metodi necessari
4. Per ogni metodo descrivere i suoi scopi, argomenti e condizioni
Java offre la possibilità di definire delle istanze di un dato tipo astratto. Il linguaggio
presenta strumenti per la definizione di classi e oggetti:
x una classe un'implementazione di un tipo di dati astratto
x un oggetto è un'istanza di una classe

Downloaded by Cheikhouna Thiam (thiamcheikhouna120@gmail.com)


lOMoARcPSD|15098180

MECCANISMI UTILI DI JAVA (ereditarietà, polimorfismo, data hiding͙)


L͛ereditarietà è il meccanismo mediante il quale una classe prende tutte le
caratteristiche di un͛altra classe definita in precedenza. La classe che eredita dalla
superclasse viene definita sottoclasse.
Il polimorfismo è la capacità che hanno oggetti di classi diverse di rispondere in
maniera diversa ad uno stesso messaggio

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:

Downloaded by Cheikhouna Thiam (thiamcheikhouna120@gmail.com)


lOMoARcPSD|15098180

1. Feedback a scala fine


1.1. Pair programming
1.2. Planning Game
1.3. Test driven development
1.4. Whole Team
2. Processo continuo
2.1. Continuous integration
2.2. Refactoring and Design Improvment
2.3. Small releases
3. Comprensione condivisa
3.1. Coding standards
3.2. Collective code ownership
3.3. Simple design
3.4. System metaphor
4. Benessere dei programmatori

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

Downloaded by Cheikhouna Thiam (thiamcheikhouna120@gmail.com)


lOMoARcPSD|15098180

PDF: tipi di dati primitivi


Esistono diversi tipi di dato, per esempio
o void: caso limite di tipo semplice, serve solo come tipo di ritorno per metodi
che in realtà non devono ritornare nulla
o tipi di dati semplici: sono dati che prendono un valore tramite l'operazione di
assegnamento svolta tramite l'operatore =
o costanti: valori numerici dal significato particolare; è buona cosa mettere
questi valori come static e final, oltre ad essere di tipo public
o char: si tratta di caratteri a 16 bit che vengono inizializzati tramite
assegnamento (default ͚\0͛)
o interi: all͛interno della categoria degli interi si distinguono byte, short, int e
long
o virgola mobile: all'interno della categoria dei virgola mobile si distinguono
float e double
o enum: insieme di etichette che rappresentano i possibili valori alternativi di
una variabile; la definizione di questi tipi di dato viene fatta in definizione
speciale di classe; pertanto, può essere dotata di attributi i costruttori e
metodi
o boolean: hanno solo due possibili valori: true o false (inizializzazione di
default); gli operatori su questi tipi di sono: && (and) || (or) ^ (xor)
! (not); gli operatori relazionali sono == != <(<=) >(>=)

Esistono anche diverse operazioni da applicare su questi tipi di dato:


o per quanto riguarda gli operatori diadici le operazioni sono 4: somma,
sottrazione, moltiplicazione e divisione; solo per gli interi vale anche
l'operazione di resto (%)
o per quanto riguarda gli operatori monadici valgono solo due operazioni:
l'incremento (++) e il decremento (--)
o operazioni di assegnamento: += -= *= /= %= (solo per interi)
o operazioni di inizializzazione con assegnamento; se non c'è assegnamento
viene stabilito per default il valore 0
Nota bene: le operazioni di assegnamento sono possibili soltanto tra tipi compatibili
oppure dello stesso tipo.
o Cast: consiste nel trasformare il valore della variabile in quello corrispondente
di un altro tipo

Downloaded by Cheikhouna Thiam (thiamcheikhouna120@gmail.com)


lOMoARcPSD|15098180

o Upcasting: quando il cambiamento del tipo di dato avviene in


automatico
o Downcasting: quando io devo fare l'operazione di cast in maniera
esplicita
o espressioni aritmetiche: vengono utilizzati dei metodi matematici forniti dalla
classe Math

Downloaded by Cheikhouna Thiam (thiamcheikhouna120@gmail.com)


lOMoARcPSD|15098180

PDF: uso di classi


Le classi, a differenza dei tipi semplici, hanno delle regole più complicate. Java, come
molti altri linguaggi di programmazione, è dotato di una libreria (library) all'interno
della quale ci sono classi pronte all'uso. Quando dobbiamo creare e usare una classe
pronta all'uso i passi da seguire sono:
™ Identificazione della classe: nella libreria Java standard è presente una
documentazione molto ampia che illustra lo scopo delle varie classi presenti
all'interno; la lettura della documentazione è un'attività tipica svolta durante
la programmazione. La libreria standard segue una linea logica: le classi simili
tra loro vengono messe all'interno dello stesso package (es: java.util). Ogni
package ha un nome composto da più parole separate da un ͞.͟ e contiene
diverse classi. Per importare all'interno del programma un determinato
package bisogna usare il termine import.

™ Istanziabilità: le classi della libreria standard si possono distinguere in classi


istanziabili e non istanziabili. La maggior parte delle classi sono istanziabili, ma
la presenza di classi non istanziabili è necessaria come, per esempio, in quella
che contiene il metodo main
o Istanziabili: oggetti con struttura simile ma proprietà distinte a livello
individuale. Rappresenta qualcosa che esiste in molteplici versioni. La si
riconosce perché possiede costruttori, gli attributi e i metodi (definiti a
livello di istanza) sono quasi tutti non static e quando devo eseguire i
metodi sento la necessità di avere un'istanza
o Non istanziabili: insieme di metodi di natura generale non legati alle
proprietà di oggetti individuali specifici. Sono classi in cui non ha senso
andare a creare un'istanza. È qualcosa che essenzialmente è unico. La si
riconosce perché mancano costruttori, gli attributi e i metodi (definiti a
livello di classe) sono tutti stati e non c'è bisogno di un'istanza
o Istanziabili ibride: classi stanziabili che contengono attributi o metodi
static; è come se la classe si compone di una parte statica e una non
statica.

™ Creazione delle istanze: tramite l'operatore new vado ad invocare il metodo


costruttore della classe scelta. Non è detto che una classe abbia solo un
costruttore

Downloaded by Cheikhouna Thiam (thiamcheikhouna120@gmail.com)


lOMoARcPSD|15098180

™ Cosa posso fare con le istanze: le principali operazioni che si possono effettuare
sulle variabili che fanno riferimento a distanze sono:

o Assegnamento: consiste nell'assegnare un valore ad una variabile; il


valore di una variabile di tipo strutturato è il riferimento ad un oggetto;
infatti, l'unico modo per poter utilizzare un oggetto è quello di passare
attraverso una variabile che ne contiene il riferimento
o Confronto: si svolge attraverso l'uso degli operatori == o !=. Se uno dei
due termini del confronto è null allora si vuole verificare se una variabile
si riferisce ad un oggetto o no; se invece i termini a confronto sono due
variabili si vuole vedere se il loro valore è uguale o diverso
o Invocazione di metodi: per ogni metodo vengono specificati un nome e
un tipo di ritorno; per invocare un metodo non static andrò ad utilizzare
il ͞.͟; ogni volta che vado viene invocato un metodo bisogna passargli gli
opportuni parametri se necessario

™ 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

™ Definizione di classi: la classe rappresenta un singolo concetto del problema


considerato e tendenzialmente a un nome che descrive il concetto. all'interno
delle varie classi possono esserci degli agenti cioè oggetti che fanno dei lavori
al posto nostro, classi di utilità cioè classi contenenti metodi statici e costanti e,
infine, programmi di avvio cioè le classiche contengono il metodo main

Downloaded by Cheikhouna Thiam (thiamcheikhouna120@gmail.com)


lOMoARcPSD|15098180

PDF: leggere e scrivere


Un altro aspetto importante dei programmi Java è quello dell'interazione con
l'utente. Il modo più comodo per poter effettuare lettura da tastiera è l'utilizzo della
classe Scanner (package: java.util). Per poter utilizzare questa classe è necessario
crearne un'istanza passando System.in come argomento al costruttore. Scanner
mette a disposizione metodi per la lettura da tastiera di valori di tipi diversi:
Î nextInt() restituisce un intero
Î nextDouble() restituisce un double
Î next() Restituisce un oggetto stringa contenente tutti i caratteri inseriti fino al
separatore
Î nextLine() Restituisce una stringa contenente i caratteri inseriti fino alla
pressione del tasto ͞invio͟
L'utente deve essere sempre guidato nell'inserimento da tastiera e inoltre è
opportuno inserire dei dati che corrispondono al tipo di dato scelto perché se per
esempio inseriamo in un'istanza di Scanner un numero quando ci si aspetta una
stringa abbiamo una brusca terminazione del programma.
Un altro modo per avere ͞un input da tastiera͞ è quello di leggere da un file di testo.
Per farlo innanzitutto si crea un'istanza di Scanner e per leggere dal file di testo si
crea un oggetto di tipo FileReader.
9 FileReader reader = new FileReader(͞input.txt͟);
Scanner in = new Scanner(reader);
Dopodiché si possono utilizzare i metodi associati all'oggetto Scanner
Esistono dei metodi standard che vengono utilizzati per convertire la sequenza di
caratteri contenuta in una stringa nel valore numerico che essa rappresenta:
a) Byte.parseByte(stringaLetta);
b) Short.parseShort(stringaLetta);
c) Integer.parseInteger(stringaLetta);
d) Long.parseLong(stringaLetta);
e) Double.parseDouble(stringaLetta);
f) Float.parseFloat(stringaLetta);
͙ sono classi stanziabili ibride definite come wrapper. A quelle già elencate si
aggiungono Boolean e Character. Queste classi forniscono metodi di utilità generale
per operare sui tipi semplici e permettono di rappresentare i tipi semplici come
oggetti (es: Integer intero = new Integer(25);)

Downloaded by Cheikhouna Thiam (thiamcheikhouna120@gmail.com)


lOMoARcPSD|15098180

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().

Downloaded by Cheikhouna Thiam (thiamcheikhouna120@gmail.com)


lOMoARcPSD|15098180

PDF: strutture di controllo


STRUTTURE DI CONTROLLO:
™ If-else: si tratta di poter scegliere tra una cosa o un͛altra
™ If isolato: è un controllo magari per dare un avviso all͛utente; si tratta di una
struttura che non ha un͛alternativa
™ Espressione con selezione: è una tipologia di if abbreviato; la struttura è del
tipo espressione booleana ? valoreT : valoreF. Se
l͛espressione booleana risulterà vera allora prenderà un valore altrimenti sarà
scelto l'altro valore
™ If annidati: si tratta di if che contengono a loro volta altri if
™ Else pendente: nel caso di if annidati ogni else si riferisce all'ultimo if aperto
che non è stato chiuso da un else
™ Confronto floating-point: per evitare errori di arrotondamento è importante
utilizzare per confrontare numeri floating point il valore assoluto, cioè vado a
vedere se questi numeri sono abbastanza vicini. Se questo risulta essere vero
allora li considero come uguali (| float1 ʹ float2 | < ɸ )
™ Switch: quando capita di dover fare molteplici scelte rappresentabili con
numeri interi o singoli caratteri. È più opportuno utilizzare lo switch piuttosto
che fare tanti if a ripetizione
™ Iterazione: ripetere un͛istruzione per un determinato numero di volte
™ Ciclo for: concepito per la ripetizione di operazioni per un numero
prefissato di volte. Ha questa struttura for(inizializzazione/i;
espressione booleana; step/s). Il corpo del ciclo for viene iterato
fino a quando la condizione di ingresso diventa falsa. in caso di errore si
verifica un ciclo infinito
™ Ciclo while: è caratterizzato da una condizione all'inizio del ciclo; non
sempre è possibile predeterminare il numero di iterazioni necessarie da fare
nel ciclo; l'uscita dal ciclo può dipendere da un'esecuzione che viene fatta
all'interno del ciclo stesso oppure la condizione iniziale diventa falsa
™ Ciclo do-while: è caratterizzato da una condizione alla fine del ciclo; può
capitare che la condizione booleana dipenda dall'esecuzione del ciclo stesso
quindi opportuno controllare l͛interazione. Il ciclo itera fino a quando la
condizione diventa falsa
™ Cicli annidati: come nel caso degli if annidati è possibile che dei cicli
contengano altri cicli
™ Break: comando che permette di uscire dal ciclo corrente
™ Continue: permette di saltare la prossima iterazione del ciclo corrente

Downloaded by Cheikhouna Thiam (thiamcheikhouna120@gmail.com)


lOMoARcPSD|15098180

PDF: definire metodi


Suddividere un problema in problemi più semplici rende più facile la comprensione e
lo sviluppo del codice. Non ci sono regole riguardo la suddivisione ma tramite
l'esperienza si sviluppa la capacità di strutturare razionalmente i programmi.
Î Il metodo main per essere ben strutturato deve essere molto breve e
deve rappresentare la sequenza dei passaggi logici senza mostrare i dettagli
realizzativi.
Î Il metodo toString si rivela essere sempre molto utile perché restituisce
la sequenza di caratteri da stampare invece che stampare direttamente a
video
Ogni metodo può avere un tipo di ritorno che può essere elementare o strutturato.
L'esecuzione di un metodo non void necessità l'istruzione return seguita da
un'espressione di tipo opportuno; invece, se il metodo è void non sarà necessario
ritornare qualcosa. Un'altra caratteristica dei metodi è la lista degli argomenti o
parametri. Sono possibili degli overloading dei metodi ma NON sul tipo ritornato
perché metodi con nome e lista degli argomenti uguali ma tipo ritornato diverso non
vengono distinti ma generano errori di compilazione.
Gli argomenti vengono passati per valore: viene effettuata una copia locale del
valore passato. Nel caso di argomenti di tipo strutturato si hanno riferimenti a
oggetti.
I metodi hanno essenzialmente due scopi:
1. restituire un valore
2. modificare un oggetto
È consigliabile che ciascun metodo soddisfi solo uno dei due scopi perché è molto
probabile che se deve modificare un oggetto allora non deve ritornare nulla e quindi
essere di tipo void; mentre se deve ritornare qualcosa non può sicuramente essere
di void.
La definizione di variabile è possibile a livello di classe o all'interno di un metodo. il
valore di default che gli viene assegnato e lo zero per i tipi numerici e il false per il
boolean anche se il compilatore pretende esplicitamente che il programmatore
inizializzi la variabile. È sbagliato considerare uguali la vita degli oggetti e la vita delle
variabili: una variabile nasce al momento della definizione, un oggetto nasce quando
viene usato l'operatore new; una variabile muore quando cessa la sua visibilità, un
oggetto muore quando nessuna variabile lo riferisce più.

Downloaded by Cheikhouna Thiam (thiamcheikhouna120@gmail.com)


lOMoARcPSD|15098180

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

Downloaded by Cheikhouna Thiam (thiamcheikhouna120@gmail.com)


lOMoARcPSD|15098180

PDF: array e Collection


Array e collection servono per rappresentare collettivamente un insieme di dati.
™ Array: la dichiarazione avviene tramite l'uso di parentesi quadre (es: nome-
tipo [] nome-variabile oppure nome-tipo nome-variabile []). Dato che si tratta
di un tipo strutturato le variabili vengono inizializzate a null e gli oggetti array
devono quindi essere costruiti. gli elementi di un array sono utilizzabili
singolarmente, la numerazione parte da zero e non da uno e infine la
dimensione dell'array la si ricava tramite l'attributo length. Quando dobbiamo
eseguire un'operazione su tutti gli elementi di un array viene spontaneo
utilizzare il ciclo for con l'utilizzo di indici. Il ciclo for può essere quello
standard (con indici) oppure può essere quello abbreviato
(for (nome-tipo nome-variabile: nome-array)).
o Copia di un array: è una delle operazioni più comuni che vengono svolte
sugli array; per farlo è stato fornito un metodo apposito chiamato
System.arraycopy
o Aumento di un array
o Rimuovere un elemento da:
o array non ordinato: bisogna sovrascrivere l'elemento che deve
essere rimosso; decremento poi l'indice che definisce il numero
di elementi dell'array
o array ordinato: anticipo tutti gli elementi successivi all'elemento
corrente che deve essere rimosso; decremento poi l'indice che
definisce il numero di elementi dell'array
o Inserire un elemento:
o array non ordinato: inserire il nuovo elemento come ultimo
elemento dell'array; incrementare l'indice che definisce il
numero di elementi dell'array
o array ordinato: dalla fine dell'array spostando di una posizione
tutti gli elementi che hanno indice maggiore rispetto a quello
corrente finché non è libera la posizione desiderata. Si inserisce
l'elemento e incremento l'indice che definisce il numero degli
elementi dell'array
Gli array di oggetti contengono riferimenti quindi con il metodo arraycopy
duplico i riferimenti e non gli oggetti.
Per rappresentare tabelle e matrici posso usare gli array multidimensionali
cioè array di array. Per scorrere questi array servono due cicli for, uno dentro
l'altro.

Downloaded by Cheikhouna Thiam (thiamcheikhouna120@gmail.com)


lOMoARcPSD|15098180

™ 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

Downloaded by Cheikhouna Thiam (thiamcheikhouna120@gmail.com)


lOMoARcPSD|15098180

PDF: progetto di classi


All'aumentare della complessità dei problemi ci sono da affrontare determinati
ostacoli, per esempio
9 numero di classi da definire
9 complessità di ciascuna classe
9 difficoltà di sviluppo del programma
9 l͛alta possibilità d͛errore
͙ si tratta di identificare i tipi di oggetti coinvolti nel problema ed individuare le loro
caratteristiche comuni essenziali. Una classe rappresenta un singolo concetto del
problema considerato, il nome dovrebbe essere in grado di descriverlo.
Bisogna comunque mantenere un buon stile e soprattutto prendere in
considerazione le varie relazioni tra le classi. Nella programmazione a oggetti un
programma è composto da più classi in relazione tra loro; se queste relazioni sono
troppo strette la composizione diventa un groviglio, segno di brutta
programmazione.
L'accesso e la modifica degli attributi è buona cosa che avvenga sempre tramite
appositi metodi della stessa classe. Per aiutarci ad evitare errori di questo tipo
possiamo utilizzare i modificatori di accesso:
x public: ovunque
x protected: all͛interno del package e delle classi derivate
x friendly: all͛interno del package (default)
x private: all͛interno della sola classe
Una classe deve offrire ad altri suoi servizi senza permettere delle violazioni; le classi
troppo permissive finiscono per essere dannose. Nel definire una classe è necessario
essere in grado di distinguere ciò che deve essere visibile all'esterno e ciò che deve
restare interno.
Per default una classe è visibile solo all'interno del suo package. Il modificatore di
classe maschera i modificatori all'interno. Gli attributi non fanno parte
dell'interfaccia ma sono una caratteristica interna; solitamente è sconsigliato
rendere gli attributi pubblici mentre è altamente consigliato renderli privati. Per
quanto riguarda i metodi, se questi sono pubblici allora definiscono la loro
interfaccia verso tutto il mondo, se sono privati allora la programmazione
strutturata all'interno della classe

Downloaded by Cheikhouna Thiam (thiamcheikhouna120@gmail.com)


lOMoARcPSD|15098180

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

Downloaded by Cheikhouna Thiam (thiamcheikhouna120@gmail.com)


lOMoARcPSD|15098180

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

Downloaded by Cheikhouna Thiam (thiamcheikhouna120@gmail.com)


lOMoARcPSD|15098180

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

Downloaded by Cheikhouna Thiam (thiamcheikhouna120@gmail.com)


lOMoARcPSD|15098180

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)

Downloaded by Cheikhouna Thiam (thiamcheikhouna120@gmail.com)


lOMoARcPSD|15098180

L'eccezione a controllo non obbligatorio rappresentano in generale le condizioni di


errore evitabile tramite una corretta programmazione
- NullPointerException, ArrayIndexOutOfBoundsException,
IllegalArgumentException
L͛eccezione a controllo obbligatorio comprende anomalie che possono verificarsi
fuori dal controllo del programmatore. È il programmatore che deve gestirle tramite
le varie regole di gestione
- IOException, FileNotFoundException, EOFException, RemoteException
Non ci sono molte vie di uscita alla gestione delle eccezioni o la si gestisce
localmente con un catch oppure si spera che la gestisca il compilatore. Se non viene
trovato alcun catch l'eccezione viene gestita dalla Java Virtual Machine
esternamente al programma e la maggior parte delle volte riporta un messaggio di
errore all'utente.
Per abilitare un programma con le asserzioni bisogna utilizzare il comando
-enableassertion o -ea; per disabilitarle bisogna usare il controllo -disableassertions
o -da. Possiamo usare le asserzioni per:
ƒ verificare invarianti
ƒ controllare il flusso, ad esempio se vogliamo che una parte del codice non
venga mai raggiunta

Downloaded by Cheikhouna Thiam (thiamcheikhouna120@gmail.com)


lOMoARcPSD|15098180

PDF: stream di dati


L'idea degli Stream è quello di avere una classe base che fornisce operazioni
elementari di lettura e scrittura a livello di byte o di caratteri. Uno Stream di input si
crea, si effettuano letture, si chiude; uno Stream di output si crea, si effettuano
scritture, si chiude. Gli Stream elementari sono molto grezzi, di norma si associa loro
un ͞filtro͟ sulle quali le operazioni di lettura e scrittura vengono trasformati in
operazioni sul flusso elementare associato.
Le classi InputStream e OutputStream sono astratte: uno Stream elementare è
un'istanza di una loro sottoclasse. L'associazione tra uno streaming il filtro avviene
tramite il costruttore:
Î Data Stream: permettono di leggere/scrivere da un sistema di byte in
variabili di tipo elementare
Î Buffered Stream: aggiungono capacità di buffering ad un input/output
Stream
Î PrintStream: permette di ottenere output formattato visualizzabile
Ricapitolando dunque ogni Stream caratterizzato come input o output; i file
vengono tipicamente riscritti da capo su un disco tramite un'istanza della classe File.
La classe File serve a rappresentare solo i nomi dei file, serve per fare riferimento ad
un file per nome e di effettuare delle operazioni sull'intero file ma non sul
contenuto. Per operare sui dati di un file con un certo nome bisogna creare
un'istanza della classe File che lo rappresenta e lo associa quindi ad uno Stream.
La classe File permette l͛uso di pathname completi ed è dotata di tre costruttori:
1. New File(String nome-file-o-dir);
2. New File(String path, String name);
3. New File(File dir, String name);
In tutti e tre i costruttori l͛operazione new File crea un oggetto che permette di fare
riferimento ad un file/directory tramite il nome
STREAM BINARI
Si tratta di file nei quali sono salvati tipi di dati elementari nel loro formato di
rappresentanza interna (8 byte per i double, 4 byte per gli int ecc). In questo ambito
vengono usate le classi DataInputStream e DataOutputStream, le quali offrono
metodi per leggere/scrivere tipi di dati elementari. È necessario chiudere lo Stream
al termine della fase di lettura/scrittura con il metodo close(). In caso contrario la
risorsa non viene liberata e l'output potrebbe non essere completamente scritto sul

Downloaded by Cheikhouna Thiam (thiamcheikhouna120@gmail.com)


lOMoARcPSD|15098180

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

Downloaded by Cheikhouna Thiam (thiamcheikhouna120@gmail.com)


lOMoARcPSD|15098180

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

Downloaded by Cheikhouna Thiam (thiamcheikhouna120@gmail.com)


lOMoARcPSD|15098180

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

Downloaded by Cheikhouna Thiam (thiamcheikhouna120@gmail.com)


lOMoARcPSD|15098180

PDF: strutture dati + Generics


Le strutture dati sono caratterizzate da un͛utilità universale e possono essere
realizzate in qualunque linguaggio di programmazione; solitamente hanno una
natura ricorsiva. A partire da Java 2 il package java.util contiene il Java Collection
Framework (JFC) cioè un insieme di interface, classi e classi astratte progettate per
facilitare la creazione e l͛utilizzo di strutture dati collettive.
Di seguito verranno elencate le principali strutture dati:
Î Tipi di dati parametrici: le definizioni di interface e classi JFC sono
parametriche rispetto ad altri tipi di dati. Sintatticamente questo concetto è
rappresentato dalle parentesi angolate <> che racchiudono il dato
parametrico.
Î Interfacce Collection, Iterable e Iterator
o Collection: è l͛ŝŶƚĞƌĨĂĐĞďĂƐĞĚĞl JFC e rappresenta una raccolta generica
di oggetti di un tipo <E>. Specifica 19 metodi tra cui, uno dei più significativi è
iterator()
o Iterable: è un͛ŝŶƚĞƌĨĂĐĞ che specifica un solo metodo, cioè iterator().
Quest͛ƵůƚŝŵŽƌĞƐƚŝƚƵŝƐĐĞun riferimento ad un Iterator<T>, ovvero un iteratore
sul tipo di oggetti contenuti nella Collection.
o Iterator: è un͛ŝŶƚĞƌĨĂĐĞĐŚĞspecifica i metodi che deve fornire un
iteratore, ovvero un oggetto capace di scorrere uno ad uno gli elementi di una
raccolta. Gli iteratori offrono un modo alternativo per compiere
un͛ŽƉĞƌĂnjŝŽŶĞƐƵƚƵƚƚŝŐůŝĞůĞŵĞŶƚŝĚŝƵŶĂŽůůĞĐtion
Î Famiglie di Collection: Set, List, Queue, Deque
o Set: è una Collection con il vincolo di non contenere elementi duplicati;
eredita tutti i metodi di Collection, senza aumentarne il numero ma ne
modifica i requisiti di alcuni in modo da evitare duplicazioni
ƒ L͛interface SortedSet estende Set con il requisito che esista una
relazione di ordine tra gli elementi in modo da selezione il primo
l͛ultimo elemento, selezionare gli elementi prima o dopo un altro
elemento oppure selezionare gli elementi di un certo range
ƒ L͛interface NavigableSet estende SortedSet con dei metodi in
aggiunta come la selezione dell͛elemento più vicino rispetto ad
un altro oppure la possibilità di enumerare il Set in ordine inverso
o List: è una Collection nella quale gli elementi sono ordinati
posizionalmente e sono disponibili operazioni riferite ad indici di posizione
ƒ L͛interface ListIterator permette movimenti bidirezionali sulla List
con modifiche del contenuto

Downloaded by Cheikhouna Thiam (thiamcheikhouna120@gmail.com)


lOMoARcPSD|15098180

o Queue: rappresenta una coda, ovvero una struttura dove si inseriscono


elementi e solo un elemento è disponibile per l͛accesso o per l͛estrazione. La
politica di selezione è il FIFO (first in first out). Esistono tre operazioni base su
una coda:
ƒ inserimento di un elemento in coda
ƒ accesso all͛elemento di testa
ƒ estrazione dell͛elemento in testa
o Deque: sta per double ended queue; è un͛interface che estende Queue
poiché rappresenta una struttura con due estremi ed operazioni di
inserimento, accesso ed estrazione su entrambi gli estremi
Î Stack: è caratterizzata da operazioni solo sulla cima della pila
o push per l͛aggiunta
o pop per l͛estrazione
o peek per l͛accesso
È una forma limitata di Deque nella quale si opera sempre in testa e mai in
coda
Î Map: è una raccolta indicizzata dove ogni elemento viene inserito
accompagnato da un altro elemento detto key che lo definisce univocamente.
Questo permette l͛accesso non solo tramite indice o iterazione ma anche
tramite chiave. L͛uso di chiavi univoche è molto diffuso per l͛identificazione di
codice fiscale, targhe, numero di matricola o codici di prenotazione.
L͛interfaccia Map<K, V> è parametrica rispetto due tipi di dati:
o K rappresenta il tipo usato come chiave
o V rappresenta il tipo degli elementi contenuti nella Map e indicizzati
dalle chiavi
L͛ŝŶƚĞƌĨĂĐĞMap ha alcuni legami con l͛ŝŶƚerface Collection come alcuni metodi
con lo stesso nome/ruolo e tre possibilità di accesso al contenuto di una Map
sottoforma di Collection
ƒ SortedMap: estende Map aggiungendo un requisito di ordinamento
totale sulle chiavi
ƒ NavigableMap: estende SortedMap con altri metodi di utilità

DALLE INTERFACCE ALLE CLASSI


Le classi ArrayList e Vector forniscono entrambe un͛implementazione dell͛interface
List.

Downloaded by Cheikhouna Thiam (thiamcheikhouna120@gmail.com)


lOMoARcPSD|15098180

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

La classe ArrayDeque offre un͛implementazione dell͛interface Deque senza alcun


metodo aggiuntivo ma non è predisposta per la programmazione multi-thread.
La classe LinkedList ha una natura multiforme in quanto implementa sia l͛interface
List sia l͛interface Deque ma non è predisposta per la programmazione multi-thread.
Si tratta di una classe generica in cui è necessario specificare il tipo di elemento
utilizzato.
ƒ ListIterator permette l͛accesso agli elementi di una LinkedList e ne identifica la
posizione
In una LinkedList bisogna fare attenzione ad invocare il metodo remove perché esso
può essere invocato solo dopo aver eseguito un next o un previous; non è possibile
invocarlo subito dopo l͛add, in tal caso viene lanciata un͛eccezione.
Inserimento e rimozione di un elemento:
ArrayList LinkedList
In media metà elementi devono essere Sono sufficienti un numero fisso di
spostati operazioni indipendentemente dalla
dimensione della lista

La classe HashSet fornisce una semplice implementazione dell͛interface Set; la classe


LinkedHashSet è una sottoclasse di HashSet e aggiunge la caratteristica di
mantenere sempre lo stesso ordine quando si effettua l͛enumerazione degli
elementi. Se si utilizza una classe propria di una collezione Hash è opportuno
ridefinire i metodi
- hashCode(): restituisce una chiave numerica che dovrebbe rappresentare un
identificativo univoco per ogni oggetto della classe
La classe TreeSet fornisce un͛implementazione dell͛interface NavigableSet e
dell͛interface Comparable.
Le tre classi, HashSet, LinkedHashSet e TreeSet, non sono predisposte per la
programmazione multi-thread.

Downloaded by Cheikhouna Thiam (thiamcheikhouna120@gmail.com)


lOMoARcPSD|15098180

Le classi HashMap e HashTable forniscono un͛implementazione dell͛interface Map


- HashTable ha alcuni metodi aggiuntivi, non ammette elementi o chiavi null ed
è predisposta per la programmazione multi-thread
La classe LinkedHashMap è una sottoclasse di HashMap e aggiunge la caratteristica
di mantenere sempre lo stesso ordine quando si effettua l͛enumerazione degli
elementi.
La classe TreeMap fornisce un͛implementazione dell͛interface NavigableMap
Le tre classi, HashMap, LinkedHashMap e TreeMap, non sono predisposte per la
programmazione multi-thread.

CLASSI E INTERFACCE GENERICHE


Le interface le classi appartenenti al JFC sono definite genericamente rispetto al tipo
di oggetto contenuto in ciascuna istanza di Collection. Questo tipo generico viene
specificato in parentesi angolari <> e viene definito parametro di tipo o variabile di
tipo.
Nella maggior parte dei casi si desidera definire le strutture dati e i metodi generici
in grado di operare su qualunque classe; questo porta al conflitto tra la genericità e
il type safety. La soluzione è la creazione di classi generiche
Î Si tratta di classi parametriche rispetto ad uno o più parametri di tipo, indicati
tra <> dopo il nome della classe. Per convenzione i parametri di tipo vengono
indicati con singole lettere maiuscole
o T, S, U per qualunque uso
o E per indicare elementi di strutture collettive
o K, V per indicare chiave e valore di Map
Î I nomi dei parametri di tipo possono essere usati come qualunque altro nome
di tipo nella definizione di una classe ma ci sono limitazioni
o Non è possibile creare istanze di tipi parametrici
o Non è possibile definire attributi static di un tipo parametrico o usare
un tipo parametrico in un metodo static
Î Al momento dell͛uso ciascun parametro di tipo generico deve essere
sostituito da un tipo strutturato (classe wrapper)
Le classi generiche (ma anche quelle normali) possono contenere metodi generici la
cui definizione dipende da uno o più variabili di tipo. Le variabili di tipo sono
specificate tra <> prima del tipo ritornato. Se un metodo generico è definito in una

Downloaded by Cheikhouna Thiam (thiamcheikhouna120@gmail.com)


lOMoARcPSD|15098180

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

LISTE CONCATENATE E ALBERI BINARI


Una lista concatenata serve per indicare una struttura nella quale di elementi sono
collegati tramite riferimenti dall͛uno all͛altro. Il caso più semplice prevede un
collegamento unidirezionale sequenziale a partire da un elemento iniziale
ƒ Lista concatenata semplice: il primo elemento viene detto testa della lista ed
è riferito da una variabile che non è un elemento della lista. Il riferimento è
necessario per accedere alla lista. Ogni elemento, tranne l͛ultimo, fa
riferimento a quello successivo
ƒ Lista concatenata doppia: ogni elemento contiene due riferimenti, uno
all͛elemento precedente e uno all͛elemento successivo. Il primo elemento
contiene solo il riferimento al successivo mentre l͛ultimo solo il riferimento al
precedente
ƒ Lista circolare semplice: l͛ultimo elemento è collegato al primo in modo da
chiudere circolarmente il collegamento
ƒ Lista circolare doppia: i riferimenti tra gli elementi realizzano un doppio anello

Gli elementi di strutture dati concatenate sono tipicamente definiti in maniera

Downloaded by Cheikhouna Thiam (thiamcheikhouna120@gmail.com)


lOMoARcPSD|15098180

ricorsiva, infatti, ogni elemento deve contenere un riferimento ad un elemento dello


stesso tipo
Î Generics e classi interne: per rappresentare una struttura dati servono
essenzialmente due classi:
ƒ una rappresenta la struttura
ƒ una rappresenta i singoli elementi
Per poter definire strutture parametriche rispetto ai dati entrambe le classi
devono essere generiche. Altrettanto importante è però definire che il tipo di
una lista e dei suoi elementi deve essere lo stesso. Questo non è possibile se
le due classi sono separate: servono le inner class.
La classe interna tipicamente non è mai public ma private; il loro utilizzo è
molto specifico in particolare quando devo fare la condivisione di una
variabile perché la classe interna sarà definita in termini della varibaile di tipo
della classe esterna

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})

Downloaded by Cheikhouna Thiam (thiamcheikhouna120@gmail.com)

Potrebbero piacerti anche