Relazioni tra i tipi in Java – Lezione 3 di Java Avanzato

Java è un linguaggio staticamente tipato:

  • “tipato” vuol dire che ad ogni espressione viene assegnato un tipo che rappresenta l’insieme di valori che l’espressione potrebbe assumere;
  • “staticamente” vuole dire che il tipo di ogni espressione deve essere noto al momento della compilazione.

Type checking: il controllo sul sistema del tipo dei dati

Il controllo che effettua il compilatore sulla validità delle operazioni è detto type checking. In Java esistono 4 tipi:

  1. tipi base;
  2. riferimenti (classi e interfacce);
  3. array;
  4. tipo nullo (null).

E’ bene specificare che c’è distinzione tra tipo dichiarato e tipo effettivo di una variabile. In particolare:

  • Si intende per tipo dichiarato il valore della variabile a tempo di compilazione e il cui valore non potrà mai essere cambiato;
  • con tipo effettivo, si fa riferimento al valore della variabile a runtime che può cambiare valore qualsiasi volta durante l’esecuzione.

Questa distinzione è molto utile quando si parla di promozione matematica quando il valore di una variabile può cambiare (ad esempio nella somma tra un valore int ed un valore double, il valore della variabile int sarà promossa a double per consentire il funzionamento dell’operazione). Le promozioni avvengono tramite degli operatori binari infissi, come: +, /, * e .

Conversione tra i tipi di dati

Le conversioni tra tipi primitivi in Java sono consentite solo se c’è un percorso nel grafo dei tipi. In realtà il grafo dei tipi è leggermene più complesso, la versione più adatta per rappresentarlo è la seguente:

Relazioni tra i tipi in Java - Lezione 3 di Java Avanzato

Come possiamo vedere, nel grafo ci sono delle linee tratteggiate. Le linee indicano che le conversioni sono consentite ma potrebbe esserci una perdita di informazione. Ad esempio dato che int e float vengono rappresentati con lo stesso numero di bit potrebbe esserci una perdita di informazioni, i tipi float vengono rappresentati in virgola mobile, di conseguenza alcuni bit verranno usati per rappresentare la mantissa ed altri l’esponente. I numeri rappresentabili con un tipo float sono molto meno rispetto a quelli rappresentabili con un tipo int, per piccoli numeri non sorgono problemi, ma per numeri più grandi potrebbe esserci perdita di informazione.

La relazione di sottotipo tra i dati

Per consentire le “conversioni” tra tipi non primitivi, è stata introdotta la relazione di sottotipo:

  1. T è sottotipo di se stesso (riflessività);
  2. T è sottotipo di Object;
  3. T estende o implementa U allora T è sottotipo di U;
  4. Il tipo nullo è sempre e comunque sottotipo di T (sottotipo di tutti i tipi non base);
  5. T è sottotipo di U allora T[] (il tipo array di T) è sottotipo di U[] (tipo array di U).

Quella appena definita è una relazione d’ordine riflessiva, antisimmetrica e transitiva.

Per poter decidere se è possibile assegnare un valore di un certo tipo T ad una variabile di tipo U utilizzeremo la relazione di assegnabilità che dice:

Dati due tipi T e U, diremo che T è assegnabile a U se:

  1. C’è una conversione implicita da T a U, se sono tipi base;
  2. T è sottotipo di U, altrimenti.

Ovviamente dato che per i tipi non primitivi ci potrebbero essere problemi ad runtime, utilizzeremo l’operatore instanceof per verificare il tipo effettivo della variabili.

Indice Lezione PrecedenteLezione Successiva

Pubblicato in Guide, Java, Programmazione Taggato con: , , , ,

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *

*