Tipi di dato e conversioni automatiche

di il
4 risposte

Tipi di dato e conversioni automatiche

C'è un passaggio del manuale Java5 di De Sio che non mi è affatto chiaro, chiedo per favore un chiarimento da parte del forum.
Nel capitolo in cui spiega i tipi di dato dice:
Consideriamo la seguente istruzione:
byte b = 50;
Questo statement è corretto. Il numero intero 50 è tranquillamente compreso
nell’intervallo di rappresentazione di un byte, che va da –128 a +127. Il
compilatore determina la grandezza del valore numerico, e controlla se è compatibile
con il tipo di dato dichiarato.
Allora consideriamo quest’altro statement:
b = b * 2;
Ciò darà luogo ad un errore in compilazione! Infatti il compilatore non eseguirà
l’operazione di moltiplicazione per controllare la compatibilità con il tipo di dato
dichiarato. Invece promuoverà automaticamente i due operandi ad int. Quindi, se
50*2 è un int, non può essere immagazzinato in b che è un byte.
Il mio dubbio è: ma se 50 ed il risultato di 50 * 2 sono compresi tra il range del tipo di dato byte -128 e +127 , perchè Java deve considerare 50 * 2 come int?
Evidentemente c'è qualcosa che mi sfugge perchè poco più avanti c'è scritto che 50 * 2 è immagazzinabile in un tipo di dato byte.

4 Risposte

  • Re: Tipi di dato e conversioni automatiche

    fmn ha scritto:


    Il mio dubbio è: ma se 50 ed il risultato di 50 * 2 sono compresi tra il range del tipo di dato byte -128 e +127 , perchè Java deve considerare 50 * 2 come int?
    Evidentemente c'è qualcosa che mi sfugge perchè poco più avanti c'è scritto che 50 * 2 è immagazzinabile in un tipo di dato byte.
    In es.:

    byte a = 50;
    byte b = 2;
    byte r = a * b;

    La terza riga NON compila. Con gli operatori binari (cioè che lavorano con 2 operandi) viene applicata la binary numeric promotion. Il risultato è come minimo un int, non più piccolo. E un int non è assegnabile direttamente/implicitamente ad un byte. Serve un cast esplicito:

    byte r = (byte) (a * b);

    allora compila e funziona e in r hai 100.

    Per completezza: nella prima/seconda riga 50 e 2 sono di tipo int. Perché qui il cast non serve? Semplicemente perché esiste un'altra regoletta, che vale solo per l'assegnamento a variabili (non vale nella invocazione di metodi): se il valore è una "costante" ed è nel range del tipo di destinazione (byte in questo caso), allora c'è un narrowing (restringimento) implicito senza bisogno di cast esplicito.
  • Re: Tipi di dato e conversioni automatiche

    andbin ha scritto:


    La terza riga NON compila. Con gli operatori binari (cioè che lavorano con 2 operandi) viene applicata la binary numeric promotion. Il risultato è come minimo un int, non più piccolo. E un int non è assegnabile direttamente/implicitamente ad un byte. Serve un cast esplicito:

    byte r = (byte) (a * b);

    allora compila e funziona e in r hai 100.
    Vediamo se ho capito: in Java qualsiasi operazione con due operandi anche se da risultato un valore compreso tra -128 e 127, non è byte ma int?
    Per completezza: nella prima/seconda riga 50 e 2 sono di tipo int.


    Ma perchè devono essere di tipo int se possono essere di tipi byte, i dati di tipo byte non occupano meno spazio nella memoria?
    Forse diventano int in automatico perchè nelle oprazioni è facile superrare i valori dei file di tipo byte?

    Altra domanda se non chiedo troppo, se io modifico la parte di codice che hai postato in questa maniera, la compilazione viene eseguita?
    int a = 50;
    int b = 2;
    int r = a * b;
    
    
  • Re: Tipi di dato e conversioni automatiche

    fmn ha scritto:


    Vediamo se ho capito: in Java qualsiasi operazione con due operandi anche se da risultato un valore compreso tra -128 e 127, non è byte ma int?
    Detto così è detto male. Ci sono una serie di regole sulla binary numeric promotion, i quattro punti basilari sono:

    - se uno degli operandi è double, l'altro è convertito a double
    - altrimenti se uno degli operandi è float, l'altro è convertito a float
    - altrimenti se uno degli operandi è long, l'altro è convertito a long
    - altrimenti entrambi gli operandi sono convertiti a int

    E non scende più sotto di int. Quindi un byte + short non fa uno short ma un int!

    Per le regole complete, ti consiglio di leggere sul Java Language Specification alla sezione 5.6.2: Binary Numeric Promotion
    Questa è una di quelle cose da sapere "a menadito".

    fmn ha scritto:


    Ma perchè devono essere di tipo int se possono essere di tipi byte, i dati di tipo byte non occupano meno spazio nella memoria?
    Forse diventano int in automatico perchè nelle oprazioni è facile superrare i valori dei file di tipo byte?
    Una costante "letterale" scritta nel sorgente come es. 123 per definizione del linguaggio è una costante int. Tutto qui. Se vuoi una costante long puoi mettere il suffisso l o (preferibilmente) L es. 123L (e ci sono anche i suffissi per costanti float e double).
    Non c'è modo di specificare una costante letterale byte o short. Non ce n'è in effetti molto bisogno grazie anche alla regola speciale del narrowing implicito nell'assegnamento di una costante ad una variabile.

    fmn ha scritto:


    Altra domanda se non chiedo troppo, se io modifico la parte di codice che hai postato in questa maniera, la compilazione viene eseguita?
    int a = 50;
    int b = 2;
    int r = a * b;
    
    Qui è tutto int ... non ci sono dubbi su cosa succede.
    E sì, compila perfettamente.
  • Re: Tipi di dato e conversioni automatiche

    Grazie anbin, sei sempre molto utile ed esaustivo.
Devi accedere o registrarti per scrivere nel forum
4 risposte