


















































Studia grazie alle numerose risorse presenti su Docsity
Guadagna punti aiutando altri studenti oppure acquistali con un piano Premium
Prepara i tuoi esami
Studia grazie alle numerose risorse presenti su Docsity
Prepara i tuoi esami con i documenti condivisi da studenti come te su Docsity
Trova i documenti specifici per gli esami della tua università
Preparati con lezioni e prove svolte basate sui programmi universitari!
Rispondi a reali domande d’esame e scopri la tua preparazione
Riassumi i tuoi documenti, fagli domande, convertili in quiz e mappe concettuali
Studia con prove svolte, tesine e consigli utili
Togliti ogni dubbio leggendo le risposte alle domande fatte da altri studenti come te
Esplora i documenti più scaricati per gli argomenti di studio più popolari
Ottieni i punti per scaricare
Guadagna punti aiutando altri studenti oppure acquistali con un piano Premium
appunti di java, relativi a exception, override, overload, java fx, thread, input/output
Tipologia: Appunti
1 / 58
Questa pagina non è visibile nell’anteprima
Non perderti parti importanti!



















































In offerta
13.4 Qual è la struttura che funziona analogamente all'iteratore e usato in ASD e perché lo si preferisce alla
1.4 Necessità dell’ausilio alla strutturazione Un software complesso e di grandi dimensioni deve garantire le seguenti proprietà:
L’elemento comune di tutte e tre le esigenze è la modularità, ovvero la creazione di unità (ad esempio i moduli della programmazione modulare o gli oggetti della OOP) internamente consistenti, cioè funzionanti e ben progettati rispetto alle specifiche del problema. Bisogna garantire una bassa interazione tra unità differenti, in modo da garantire un certo grado di indipendenza tra unità che favorisca la manutenzione, la verifica degli errori e la riusabilità.
Un linguaggio di programmazione può mettere a disposizione dei costrutti più o meno efficaci per permettere una facile strutturazione del codice al fine di ottenere i tre requisiti detti. Una buona progettazione, ovviamente, garantisce i tre requisiti in qualsiasi linguaggio. Una buona progettazione è comunque necessaria per utilizzare nel modo migliore i meccanismi forniti dal linguaggio.
2.4 Differenza tra classe ed oggetto In un linguaggio orientato agli oggetti una classe consente di definire un nuovo tipo per il linguaggio, mentre un oggetto è una informazione di tale tipo.
La classe definisce la struttura dati (attributi), l’oggetto possiede un proprio stato (valori degli attributi).
La definizione di una classe è una descrizione degli attributi e dei metodi definiti per tutti gli oggetti che la classe rappresenta: l’utente non usa una classe, ma uno o più oggetti costruiti a partire da una classe. Gli oggetti rappresentano le istanze di una classe.
2.5 Definizione di metodo Un metodo (o anche funzione membro), in informatica, è un termine che viene usato principalmente nel contesto della programmazione orientata agli oggetti per indicare un sottoprogramma associato in modo esclusivo ad una classe e che rappresenta (in genere) un'operazione eseguibile sugli oggetti e istanze di quella classe.
Un metodo consiste di:
2.6 Definizione di messaggio Un messaggio è una richiesta di comunicazione con una istanza al fine di richiederne l’esecuzione di un’operazione (attraverso il metodo corrispondente).
Per inviare un messaggio sono necessari:
2.7 Incapsulamento: funzionamento e vantaggi L’Information Hiding (oppure incapsulamento) è la proprietà per cui un oggetto rende inaccessibili all’esterno (incapsula) gli attributi (dati) e i metodi (procedure) che accedono ai dati stessi. Lo scopo principale è dare accesso ai dati incapsulati solo attraverso i metodi definiti nell'interfaccia, permettendo un solo punto di accesso ai dati. L’incapsulamento risponde all’esigenza di strutturazione del codice.
L'incapsulamento permette di vedere l'oggetto come una blackbox, cioè una scatola nera: attraverso l'Interfaccia sappiamo l’oggetto cosa fa e come interagisce con l'esterno, ma non come lo fa.
L’insieme di più oggetti appartenenti a classi diverse e l’interazione tra tali oggetti realizza una certa funzionalità del problema. Gli oggetti, quindi, non sono indipendenti dagli altri oggetti nella realizzazione di una certa funzionalità. L’information hiding permette di ridurre la dipendenza tra gli oggetti e di controllare tale dipendenza grazie all’accesso unico ai dati attraverso i servizi: la struttura interna di una classe può cambiare senza impatti sugli oggetti di altre classi. Grazie all’incapsulamento, non esistono dati comuni tra oggetti di classi diverse e non esistono funzionalità che agiscono contemporaneamente su dati di oggetti di classi diverse.
I tipi non primitivi vengono gestiti secondo la semantica dei riferimenti, ovvero il suo riferimento conterrà l’indirizzo di memoria nel quale è stato allocato l’oggetto “riferito” (se è stato allocato, altrimenti conterrà un null pointer).
Quando viene istanziato l’oggetto di una classe con un costruttore, viene allocata la memoria necessaria nell’heap inizializzando tutte le sue variabili, e ne viene restituito il riferimento.
Possiamo sintetizzare l’utilizzo della memoria con il seguente schema:
3.5 Il passaggio di parametri avviene per valore o per riferimento? Il passaggio di parametri in Java avviene sempre per valore.
Quando si invoca un metodo che come parametro prende in input una variabile, al metodo stesso viene passato solo il valore (una copia) della variabile che quindi rimane immutata anche dopo l’esecuzione del metodo. Le modifiche effettuate all’interno di tale metodo (sulla copia) non verranno viste all’esterno.
Stesso discorso vale per i tipi reference: viene sempre passato il valore (una copia) del reference, anche se ovviamente entrambi i riferimenti, sia l’originale che la copia, punteranno allo stesso oggetto.
Il passaggio di parametri per riferimento non è stato importato in Java perché considerata una minaccia alla sicurezza.
3.6 Vantaggi della semantica dei riferimenti Dato che l’identificativo da manipolare è un riferimento a un oggetto, possono esistere più riferimenti che puntano allo stesso oggetto. La semantica per riferimenti risulta comoda in quanto consente l’allocazione dinamica (ovvero a run-time) della memoria dedicata all’oggetto nella heap, e dunque impiegando la memoria del record di attivazione soltanto per salvare il riferimento, molto più leggero.
3.7 Le naming conventions di Java In Java esistono delle regole di denominazione (alcune sono consigliate altre obbligatorie):
3.8 La firma di un metodo La coppia costituita dal nome del metodo e l’eventuale lista dei parametri viene detta firma (signature) del metodo.
Si noti che il tipo di ritorno ed i modificatori di accesso non fanno parte della firma del metodo.
3.9 Cast Il casting è un processo tramite il quale da una informazione di un certo tipo (quindi anche un oggetto di una certa classe) si ottiene una informazione di un altro tipo. Il casting non modifica l’informazione, ma crea una nuova informazione del nuovo tipo (sfruttando l’informazione di origine). Possiamo avere sia il casting di tipi primitivi, oppure il casting tra oggetti in una gerarchia di classi.
3.10 Casting tra tipi primitivi Esiste una tecnica per forzare una certa quantità ad essere immagazzinata in un certo tipo di dato. Questa tecnica è nota come cast (o casting).
Se il tipo di dato di destinazione non può immagazzinare il valore nel modo corretto, ci sarà una perdita di precisione: ad esempio, castando da int (32 bit) a byte (8 bit), saranno troncati i primi 24 bit dell’int. In alcuni casi, invece, non c’è perdita di informazione, ad esempio effettuando la conversione da int a float. Al contrario, convertendo da float ad int, ci sarà una perdita di informazione, infatti un valore reale ha uno spazio di rappresentazione più ampio di un valore intero.
Quando un casting implicito implica una perdita di informazione, il compilatore genera un errore: per forzare il casting, si può effettuare un casting esplicito tramite l’operatore (tipoDiDestinazione) , in modo tale che il valore venga prima approssimato o troncato e poi assegnato alla variabile specificata.
3.11 La parola chiave this La parola chiave this è utilizzabile soltanto dall’interno di metodi non static, e riferisce il riferimento all’oggetto per cui è stato chiamato il metodo, vale a dire l’oggetto corrente.
3.15 Come vengono inizializzati gli attributi static? Per un attributo statico c’è allocazione di memoria senza che venga istanziato un oggetto in fase di caricamento della classe, quindi può essere inizializzato in fase di definizione.
4 CREAZIONE E DISTRUZIONE DI UN OGGETTO
4.1 Differenza tra creazione di un oggetto e creazione di un
riferimento Quando si crea un riferimento ad un oggetto, non viene automaticamente generato un oggetto. Non sarà dunque possibile invocare i metodi della classe specificata, in quanto il riferimento viene inizializzato di default con il valore null, ed il tentativo di accedervi risulterà in una NullPointerException (eccezione runtime).
Per creare un oggetto bisogna utilizzare l’operatore new seguito dal costruttore della classe specificata. È l’operatore new a restituire il riferimento all’oggetto appena creato, in quanto il costruttore in sé non ha alcun valore di ritorno.
4.2 Il costruttore Il costruttore è un metodo che si assicura che l’oggetto sia inizializzato correttamente prima di essere utilizzato. Il costruttore non restituisce alcun valore (ma non si può dire che il tipo di ritorno sia void). Tuttavia, il costruttore può prendere in input parametri come un metodo qualsiasi e grazie all’overload è possibile definire più costruttore all’interno della stessa classe.
Attenzione: se definiamo un costruttore in una classe, il costruttore di default non verrà generato.
In Java il nome del costruttore è lo stesso della classe: si noti che non viene rispettata la naming convention secondo la quale la prima lettera dei metodi deve essere minuscola.
4.3 Un costruttore senza parametro è chiamato costruttore di
default? No, un costruttore senza parametri inserito dal programmatore non si chiama costruttore di default, è solo un costruttore senza parametri (no-arg constructor).
4.4 Cos’è l’identificatore di un oggetto? È il suo puntatore? In Java, l’identificativo da manipolare è un riferimento a un oggetto. Fin quando viene conservato il riferimento all’oggetto, è possibile accedervi. Il riferimento può essere considerato un “puntatore nascosto”, tramite il quale è possibile accedere alla porzione di memoria che contiene l’oggetto (non è possibile utilizzare operazioni di basso livello per i puntatori). Quando un oggetto non ha più riferimenti che puntano ad esso, può essere deallocato dal Garbage Collector.
5.3 Il metodo equals Il metodo equals(), della classe Object, è progettato per confrontare due reference (sul primo viene chiamato il metodo e il secondo viene passato come parametro) e restituisce un valore booleano true se e solo se i due reference puntano ad uno stesso oggetto (stesso indirizzo di puntamento).
Ma questo tipo di confronto è fattibile anche mediante l’operatore ==. La classe Object, infatti, è troppo generica per poter avere un’implementazione più accurata, per cui nella maggior parte delle sottoclassi di Object, (per esempio String), il metodo equals() va riscritto (override) in modo tale da restituire true anche nel caso di confronto tra due reference che puntano ad oggetti diversi, ma con gli stessi contenuti.
Dovrebbe essere questo il vero scopo di un metodo come equals(). Se vogliamo confrontare due oggetti creati da una nostra classe, quindi, dovremmo effettuare l’override del metodo equals(), in modo tale che questo restituisca true se le variabili d’istanza dei due oggetti coincidono.
5.4 Il metodo hashCode Il metodo hashCode() viene utilizzato da alcune classi del framework Collections. Esso ha un ruolo complementare al metodo equals() per confrontare l’uguaglianza di due oggetti presenti nella stessa collezione. Un hash code non è altro che un int che rappresenta un oggetto.
Un buon algoritmo di hash dovrebbe costituire un compromesso accettabile tra precisione e performance, ma la sua implementazione dipende anche dalle esigenze dell’applicazione.
5.5 Il metodo toString Il metodo toString() ha il compito di restituire una stringa descrittrice dell’oggetto. Nella classe Object, che astrae il concetto di oggetto generico, tale metodo non poteva adempiere a questo scopo, giacché un’istanza della classe Object non ha variabili d’istanza che la caratterizzano. I progettisti di Java decisero quindi di implementare il metodo toString() in modo tale che questo restituisse una stringa contenente informazioni sul reference.
5.6 Il metodo compareTo Il metodo compareTo() viene chiamato su un oggetto e gli viene passato un oggetto (solitamente) della stessa classe, e quindi il confronto all’interno del metodo viene fatto tra l’oggetto corrente e l’oggetto passato in input.
Il contratto del metodo compareTo(), dice che il metodo deve ritornare un valore negativo se l’oggetto corrente è minore dell’oggetto in input. Deve ritornare 0 se i due oggetti sono identici. E deve tornare un valore positivo nel caso l’oggetto corrente sia maggiore dell’oggetto in input.
5.7 Relazione tra equals, hashCode e compareTo I metodi equals() ed hashCode() sono strettamente legati: se facciamo override del metodo equals(), dovremmo anche fare override di hashCode() e viceversa.
Di norma, vorrete fare in modo che compareTo() produca un ordinamento naturale e coerente con il metodo equals(): se equals() restituisce true da un determinato confronto, compareTo() dovrebbe fornire un risultato zero per lo stesso confronto; analogamente, se equals() restituisce false anche compareTo() dovrebbe restituire un risultato diverso da zero per quel confronto.
5.8 L’interfaccia Comparator L’interfaccia funzionale Comparable definisce un unico metodo astratto: compare(), che prende in input due istanze della classe (che corrisponde al tipo generico di parametro) da comparare. Il contratto del metodo compare() è identico al contratto del metodo compareTo().
5.9 L’interfaccia Comparable L’ordinamento in Java richiede la definizione di un metodo che gestisca i criteri di ordinamenti di oggetti. L’interfaccia funzionale Comparable definisce un unico metodo astratto: compareTo().
Tutte le classi che implementano l'interfaccia Comparable specificano come tipo parametro per Comparable la classe stessa, per garantire che l'ordinamento sarà fatto solo tra oggetti istanziati dalla stessa classe.
5.10 Differenza tra Comparator e Comparable L’interfaccia Comparator è molto simile a Comparable, ma non appartiene al package java.lang, bensì al package java.util.
La differenza tra il metodo compare() di Comparator e il metodo compareTo() di Comparable, è che compare() viene chiamato su un’istanza di Comparator e prende in input le due istanze della classe (che deve corrispondere al tipo generico) che bisogna comparare.
5.11 Oggetti immutabili Ci sono alcuni oggetti sui quali non è possibile operare direttamente: un oggetto è immutabile se, una volta istanziato, non è possibile modificarne il contenuto.
Un oggetto String, ad esempio, è immutabile: ciò vuol dire che, una volta istanziata una stringa, il suo contenuto non può cambiare. I metodi della classe String che operano sulla stringa ne restituiscono una nuova istanza.