Docsity
Docsity

Prepara i tuoi esami
Prepara i tuoi esami

Studia grazie alle numerose risorse presenti su Docsity


Ottieni i punti per scaricare
Ottieni i punti per scaricare

Guadagna punti aiutando altri studenti oppure acquistali con un piano Premium


Guide e consigli
Guide e consigli


java document - appunti di java, Appunti di Programmazione Java

appunti di java, relativi a exception, override, overload, java fx, thread, input/output

Tipologia: Appunti

2020/2021
In offerta
30 Punti
Discount

Offerta a tempo limitato


Caricato il 12/01/2021

terosef
terosef 🇮🇹

1 documento

1 / 58

Toggle sidebar

Questa pagina non è visibile nell’anteprima

Non perderti parti importanti!

bg1
APPUNTI DI
PROGRAMMAZIONE AD
OGGETTI
A cura di Gerardo Cicalese
SOMMARIO
1 Ruolo di un linguaggio di programmazione....................................................................................................... 6
1.1 Lo spazio del problema ............................................................................................................................. 6
1.2 Lo spazio della soluzione ........................................................................................................................... 6
1.3 Il processo di astrazione ............................................................................................................................ 6
1.4 Necessità dell’ausilio alla strutturazione .................................................................................................. 7
2 Modello object oriented ................................................................................................................................... 9
2.1 Concetti fondamentali della programmazione ad oggetti ........................................................................ 9
2.2 Definizione di oggetto ............................................................................................................................... 9
2.3 Definizione di classe .................................................................................................................................. 9
2.4 Differenza tra classe ed oggetto ............................................................................................................. 10
2.5 Definizione di metodo ............................................................................................................................. 10
2.6 Definizione di messaggio ........................................................................................................................ 10
2.7 Incapsulamento: funzionamento e vantaggi .......................................................................................... 11
3 Piattaforma e linguaggio Java ......................................................................................................................... 12
3.1 I principi della piattaforma Java .............................................................................................................. 12
3.2 La JVM ..................................................................................................................................................... 12
3.3 Compilazione dei codici sorgente ........................................................................................................... 12
3.4 Gestione della memoria .......................................................................................................................... 12
3.5 Il passaggio di parametri avviene per valore o per riferimento? ............................................................ 13
3.6 Vantaggi della semantica dei riferimenti ................................................................................................ 13
3.7 Le naming conventions di Java................................................................................................................ 14
3.8 La firma di un metodo ............................................................................................................................. 14
3.9 Cast ......................................................................................................................................................... 14
3.10 Casting tra tipi primitivi ........................................................................................................................... 14
pf3
pf4
pf5
pf8
pf9
pfa
pfd
pfe
pff
pf12
pf13
pf14
pf15
pf16
pf17
pf18
pf19
pf1a
pf1b
pf1c
pf1d
pf1e
pf1f
pf20
pf21
pf22
pf23
pf24
pf25
pf26
pf27
pf28
pf29
pf2a
pf2b
pf2c
pf2d
pf2e
pf2f
pf30
pf31
pf32
pf33
pf34
pf35
pf36
pf37
pf38
pf39
pf3a
Discount

In offerta

Anteprima parziale del testo

Scarica java document - appunti di java e più Appunti in PDF di Programmazione Java solo su Docsity!

APPUNTI DI

PROGRAMMAZIONE AD

OGGETTI

A cura di Gerardo Cicalese

13.4 Qual è la struttura che funziona analogamente all'iteratore e usato in ASD e perché lo si preferisce alla

  • 1 Ruolo di un linguaggio di programmazione....................................................................................................... SOMMARIO
    • 1.1 Lo spazio del problema
    • 1.2 Lo spazio della soluzione...........................................................................................................................
    • 1.3 Il processo di astrazione............................................................................................................................
    • 1.4 Necessità dell’ausilio alla strutturazione
  • 2 Modello object oriented
    • 2.1 Concetti fondamentali della programmazione ad oggetti
    • 2.2 Definizione di oggetto
    • 2.3 Definizione di classe
    • 2.4 Differenza tra classe ed oggetto
    • 2.5 Definizione di metodo.............................................................................................................................
    • 2.6 Definizione di messaggio
    • 2.7 Incapsulamento: funzionamento e vantaggi
  • 3 Piattaforma e linguaggio Java
    • 3.1 I principi della piattaforma Java
    • 3.2 La JVM
    • 3.3 Compilazione dei codici sorgente
    • 3.4 Gestione della memoria
    • 3.5 Il passaggio di parametri avviene per valore o per riferimento?............................................................
    • 3.6 Vantaggi della semantica dei riferimenti
    • 3.7 Le naming conventions di Java................................................................................................................
    • 3.8 La firma di un metodo.............................................................................................................................
    • 3.9 Cast
    • 3.10 Casting tra tipi primitivi...........................................................................................................................
    • 3.11 La parola chiave this................................................................................................................................
    • 3.12 Il modificatore final
    • 3.13 La parola chiave static
    • 3.14 In quali casi ha senso utilizzare dei metodi statici?
    • 3.15 Come vengono inizializzati gli attributi static?
  • 4 Creazione e distruzione di un oggetto
    • 4.1 Differenza tra creazione di un oggetto e creazione di un riferimento
    • 4.2 Il costruttore
    • 4.3 Un costruttore senza parametro è chiamato costruttore di default?
    • 4.4 Cos’è l’identificatore di un oggetto? È il suo puntatore?
    • 4.5 Il Garbage Collector.................................................................................................................................
  • 5 Metodi per operare sugli oggetti
    • 5.1 Classe Object
    • 5.2 I metodi getter e setter
    • 5.3 Il metodo equals
    • 5.4 Il metodo hashCode
    • 5.5 Il metodo toString
    • 5.6 Il metodo compareTo..............................................................................................................................
    • 5.7 Relazione tra equals, hashCode e compareTo
    • 5.8 L’interfaccia Comparator
    • 5.9 L’interfaccia Comparable
    • 5.10 Differenza tra Comparator e Comparable
    • 5.11 Oggetti immutabili
  • 6 Package e modificatori
    • 6.1 Package
    • 6.2 Modificatori
    • 6.3 Visibilità e modificatori di accesso
    • 6.4 Relazione tra incapsulamento e visibilità
    • 6.5 Tipi wrapper
  • 7 Polimorfismo ed ereditarietà
    • 7.1 Polimorfismo
    • 7.2 Come fa la JVM a decidere quale metodo eseguire in presenza di polimorfismo (per metodi)?...........
    • 7.3 Binding dinamico e statico
    • 7.4 Casting tra oggetti: upcast e downcast
    • 7.5 Overloading dei metodi
    • 7.6 Come fa la JVM a distinguere i metodi overloaded?
    • 7.7 Overloading degli operatori
    • 7.8 Relazione tra overload e polimorfismo
    • 7.9 Override
    • 7.10 Annotazione @Override
    • 7.11 Differenza tra override ed overload........................................................................................................
    • 7.12 Ereditarietà
    • 7.13 Vantaggi dell’ereditarietà
    • 7.14 Visibilità dei metodi nella classe figlia
    • 7.15 Relazione tra ereditarietà e polimorfismo
    • 7.16 Operatore instanceof
    • 7.17 Parola chiave super
  • 8 Aggregazione e composizione
    • 8.1 Aggregazione...........................................................................................................................................
    • 8.2 Composizione
    • 8.3 Differenze tra aggregazione e composizione
  • 9 Classi astratte ed interfacce
    • 9.1 Classe astratta
    • 9.2 Metodo astratto......................................................................................................................................
    • 9.3 Interfaccia
    • 9.4 Differenza tra interfaccia e classe astratta
    • 9.5 Invocazione virtuale dei metodi..............................................................................................................
  • 10 Classi innestate
    • 10.1 Classi innestate e classi interne
    • 10.2 Vantaggi delle classi innestate e casi di utilizzo
    • 10.3 Classi locali
    • 10.4 Classi anonime
  • 11 Generics...........................................................................................................................................................
    • 11.1 Polimorfismo parametrico
    • 11.2 Genericità e vantaggi
    • 11.3 Tipi generici
    • 11.4 Metodi generici
  • 12 Gestione delle condizioni anomale
    • 12.1 Gestione tradizionale delle condizioni anomale e problematiche
    • 12.2 Le eccezioni in Java
    • 12.3 Operatore throw
    • 12.4 Handler....................................................................................................................................................
    • 12.5 Try with resources...................................................................................................................................
    • 12.6 Firma di un metodo che lancia eccezioni
    • 12.7 Definizione di un’eccezione
    • 12.8 Come capire se un’eccezione è controllata?
    • 12.9 Eccezioni controllate e non controllate
  • 13 Collections
    • 13.1 Schema gerarchico delle Collections
    • 13.2 Iterare sulle collezioni
    • 13.3 Iteratore
    • 13.5 Polimorfismo nelle collezioni lista? Errore. Il segnalibro non è definito.
    • 13.6 Definizione di Map
    • 13.7 Differenza tra Map e Set
    • 13.8 Vari tipi di Map........................................................................................................................................
    • 13.9 Parola chiave Iterable
    • 13.10 Come si applica e a cosa si applica il metodo hasNext()
  • 14 Streams e serializzazione.................................................................................................................................
    • 14.1 Differenza tra FileReader, FileWriter, FileInputStream, FileOutputStream e File
    • 14.2 Serializzazione
    • 14.3 Bufferizzazione: definizione, vantaggi e svantaggi
  • 15 Programmazione multi-threaded
    • 15.1 Thread
    • 15.2 Differenza tra thread e processo
    • concorrente e parallela, e differenza tra single thread e multi thread 15.3 Multithreading nel single-core e dual-core (o multi-core), ovvero differenza tra programmazione
    • 15.4 Creazione di un thread in Java, differenza tra Runnable e Thread
    • 15.5 Sincronizzazione tra thread
    • 15.6 Mutex
    • 15.7 Deadlock
    • 15.8 Synchronized
    • 15.9 Differenze tra attesa attiva ed attesa passiva.........................................................................................
    • 15.10 Differenza tra wait, sleep e join
    • 15.11 Metodo sleep()
    • 15.12 Metodo join()
    • 15.13 Metodi wait(), notify() e notifyAll().....................................................................................................
  • 16 Interfacce grafiche con JavaFX
    • 16.1 Anatomia di un’applicazione JavaFX
    • 16.2 Gestione degli eventi
    • 16.3 Properties................................................................................................................................................
    • 16.4 Binding
    • 16.5 Osservabilità............................................................................................................................................
    • 16.6 FXCollections
    • 16.7 Pattern MVC............................................................................................................................................
    • 16.8 JavaFX è una realizzazione del pattern MVC?.........................................................................................
    • 16.9 FXML
    • 16.10 Scene Builder
    • 16.11 Controller
    • 16.12 FileChooser
    • 16.13 Concorrenza in JavaFX
    • 16.14 La classe Task
    • 16.15 La classe Service
  • Programmazione Procedurale: affronta la complessità dei problemi definendo delle scatole nere a livello funzionale, cioè blocchi di codice verificati e funzionanti; le funzioni rappresentano la controparte funzionale dello spazio del problema; l’insieme di dati e funzioni definiscono lo spazio della soluzione.
  • Programmazione Modulare: le procedure con funzionalità comuni sono raggruppate in moduli; un programma è costituito da una serie di moduli che interagiscono attraverso la chiamata alle procedure; ogni modulo può contenere propri dati su cui le procedure operano.
  • Programmazione Orientata agli Oggetti: viene analizzato il problema individuando le entità indipendenti (chiamate oggetti) che sono in relazione con altre; le entità non vengono scelte perché facilmente traducibili nella logica di programmazione, ma in quanto esistono nel dominio del problema: l’obiettivo è tradurre facilmente entità del problema in oggetti del programma.

1.4 Necessità dell’ausilio alla strutturazione Un software complesso e di grandi dimensioni deve garantire le seguenti proprietà:

  • Manutenibilità: o Il codice deve essere chiaro ed auto-consistente così da favorire operazioni di manutenzione. o Gli oggetti sono entità indipendenti per quanto riguarda la struttura dati che conservano al loro interno. o Essendo le informazioni di un oggetto accessibili solo attraverso i metodi possiamo modificare la struttura interna della classe dell’oggetto senza influire su oggetti di altre classi. o Nella programmazione procedurale le funzioni potendo accedere ai dati comuni senza un controllo rendono difficile la manutenzione.
  • Verificabilità: o Il codice deve poter essere facilmente testabile al fine di verificarne la correttezza. o Gli oggetti sono entità indipendenti per quanto riguarda la struttura dati, ma anche per quanto riguarda le funzionalità intrinseche fornite da ognuno di essi. o Una volta verificato che tutti gli oggetti dell’applicazione funzionano correttamente e che rispondono in modo opportuno ad una richiesta di servizio, allora si ha la garanzia che il software che usa tali oggetti funzionerà correttamente. o I dati non possono essere modificati dall’esterno in modo improprio come può succedere nella programmazione procedurale. o Se al programma vengono aggiunte delle parti nuove non ci sono effetti collaterali sugli oggetti già funzionanti.
  • Riusabilità: o Il codice prodotto deve poter essere riutilizzato in altri sistemi software, conservando le caratteristiche ancora utili del vecchio software (eventualmente modificandole) e aggiungendo nuove proprietà. o Il riuso del codice è possibile se si riesce a separare facilmente una parte di codice utile rispetto al resto del software. o La separabilità è più facile quanto più è modulare il codice.

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:

  • Una firma (signature) ovvero la definizione/dichiarazione del metodo con tipo di ritorno, nome del metodo, tipo e nome degli eventuali parametri passati in input (detti parametri formali); in genere sono presenti alcuni indicatori aggiuntivi che consentono di ottenere l'incapsulamento delle informazioni.
  • Il corpo del metodo, opportunamente delimitato da inizio e fine, con all'interno una o più sequenze o blocchi di istruzioni scritte per eseguire una determinata azione eventualmente attraverso strutture di controllo del flusso di esecuzione quali selezioni/controllo e iterazione/cicli e sulla base dei parametri passati in input, in grado di restituire al programma chiamante un valore di ritorno (o di output) dello stesso tipo di quello dichiarato nella firma iniziale. Inoltre, nei linguaggi che dispongono di un meccanismo di gestione delle eccezioni, il blocco del metodo può terminare sollevando un'eccezione nel caso si verifichi una situazione anomala che impedisce il corretto completamento delle sue operazioni.

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:

  • L’identificatore dell’istanza alla quale viene inviato il messaggio.
  • L’identificatore del messaggio.
  • Gli argomenti che vengono scambiati fra chi invia il messaggio e l’istanza che lo riceve.

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:

  • Segmento testo o Codice eseguibile
  • Segmento dati o Dati statici  Variabili statiche: utilizzate durante tutta l’esecuzione del programma o Dati dinamici  Stack: gestito con politica LIFO - Record di attivazione o Variabili primitive  Heap: gestito con algoritmi di tipo best-fit, worst-fit, etc. - Oggetti

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

  • Il nome di una classe inizia con la lettera maiuscola.
  • I nomi di attributi, metodi e oggetti iniziano con la lettera minuscola.
  • Tutti i nomi adottano lo stile “CamelCase” (ovvero le iniziali delle parole sono in maiuscolo e tutte le altre in minuscolo).
  • Il nome del file DEVE coincidere con il nome della classe contenuta nel file.

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.