Conversioni primitive Java

1. Introduzione

Java è un linguaggio tipizzato, il che significa che utilizza il concetto di tipi. Esistono due gruppi di tipi distinti:

  1. tipi di dati primitivi
  2. tipi di dati astratti.

In questo articolo, ci concentreremo sulle conversioni di tipi primitivi.

2. Panoramica delle primitive

La prima cosa che dobbiamo sapere è che tipo di valori possono essere usati con i tipi primitivi. Esistono otto tipi primitivi che sono:

  • byte - 8 bit e con segno

  • breve - 16 bit e con segno

  • char - 16 bit e senza segno, in modo che possa rappresentare caratteri Unicode

  • int - 32 bit e con segno

  • lungo - 64 bit e con segno

  • float - 32 bit e con segno

  • doppio - 64 bit e con segno

  • booleano : non è numerico, può contenere solovalori veri o falsi

Questa non vuole essere una discussione approfondita sulle primitive e parleremo un po 'di più dei loro dettagli se necessario durante le conversioni.

3. Ampliamento delle conversioni primitive

Quando abbiamo bisogno di convertire da una primitiva che è più semplice o più piccola del tipo di destinazione, non dobbiamo usare alcuna notazione speciale per questo:

int myInt = 127; long myLong = myInt;

Durante la conversione dell'ampliamento, il valore primitivo più piccolo viene posizionato su un contenitore più grande, il che significa che tutto lo spazio extra, a sinistra del valore, viene riempito di zeri. Questo può anche essere usato per passare dal gruppo intero al punto mobile:

float myFloat = myLong; double myDouble = myLong;

Ciò è possibile perché il passaggio a una primitiva più ampia non perde alcuna informazione.

4. Restringere la conversione primitiva

A volte è necessario adattare un valore più grande del tipo utilizzato nella dichiarazione della variabile. Ciò potrebbe causare la perdita di informazioni poiché alcuni byte dovranno essere eliminati.

In questo caso, dobbiamo esprimere esplicitamente che siamo consapevoli della situazione e siamo d'accordo con questo, utilizzando un cast:

int myInt = (int) myDouble; byte myByte = (byte) myInt;

5. Conversione primitiva allargata e restringente

Questa situazione si verifica in un caso molto specifico quando vogliamo convertire da un byte a un carattere . La prima conversione è l'allargamento del byte di int e quindi dalla int viene ridotta a char .

Un esempio chiarirà questo punto:

byte myLargeValueByte = (byte) 130; //0b10000010 -126

La rappresentazione binaria di 130 è la stessa per -126, la differenza è l'interpretazione del bit di segnale. Ora convertiamo da byte a char :

char myLargeValueChar = (char) myLargeValueByte; //0b11111111 10000010 unsigned value int myLargeValueInt = myLargeValueChar; //0b11111111 10000010 65410

La rappresentazione char è un valore Unicode, ma la conversione in un int ci ha mostrato un valore molto grande che ha gli 8 bit inferiori esattamente uguali a -126.

Se lo convertiamo di nuovo in byte otteniamo:

byte myOtherByte = (byte) myLargeValueInt; //0b10000010 -126

Il valore originale che abbiamo utilizzato. Se l'intero codice inizia con un carattere, i valori saranno diversi:

char myLargeValueChar2 = 130; //This is an int not a byte! //0b 00000000 10000010 unsigned value int myLargeValueInt2 = myLargeValueChar2; //0b00000000 10000010 130 byte myOtherByte2 = (byte) myLargeValueInt2; //0b10000010 -126

Sebbene la rappresentazione in byte sia la stessa, che è -126, la rappresentazione in caratteri ci fornisce due caratteri diversi.

6. Conversione Boxe / Unboxing

In Java, abbiamo una classe wrapper per ogni tipo primitivo, questo è un modo intelligente per fornire ai programmatori metodi di elaborazione utili, senza il sovraccarico di avere tutto come riferimento a un oggetto pesante. A partire da Java 1.5 la capacità di convertire automaticamente in / da una primitiva a un oggetto e viceversa è stata inclusa ed è ottenuta mediante semplice attribuzione:

Integer myIntegerReference = myInt; int myOtherInt = myIntegerReference;

7. Conversioni di stringhe

Tutti i tipi primitivi possono essere convertiti in String tramite le loro classi wrapper, che sovrascrivono il metodo toString () :

String myString = myIntegerReference.toString();

Se dobbiamo tornare a un tipo primitivo, dobbiamo utilizzare un metodo di analisi definito dalla corrispondente Classe Wrapper:

byte myNewByte = Byte.parseByte(myString); short myNewShort = Short.parseShort(myString); int myNewInt = Integer.parseInt(myString); long myNewLong = Long.parseLong(myString); float myNewFloat = Float.parseFloat(myString); double myNewDouble = Double.parseDouble(myString); 
boolean myNewBoolean = Boolean.parseBoolean(myString);

The only exception here is the Character Class because a String is made of chars anyway, this way, considering that probably the String is made of a single char, we can use the charAt() method of the String class:

char myNewChar = myString.charAt(0);

8. Numeric Promotions

To execute a binary operation, it is necessary that both operands are compatible in terms of size.

There is a set of simple rules that apply:

  1. If one of the operands is a double, the other is promoted to double
  2. Otherwise, if one of the operands is a float, the other is promoted to float
  3. Altrimenti, se uno degli operandi è lungo , l'altro viene promosso a lungo
  4. Altrimenti, entrambi sono considerati int

Vediamo un esempio:

byte op1 = 4; byte op2 = 5; byte myResultingByte = (byte) (op1 + op2);

Entrambi gli operandi sono stati promossi a int e il risultato deve essere nuovamente convertito in byte .

9. Conclusione

La conversione tra i tipi è un'attività molto comune nelle attività di programmazione quotidiana. Esiste un insieme di regole che governano i modi in cui i linguaggi tipizzati staticamente operano tali conversioni. La conoscenza di queste regole può far risparmiare molto tempo quando si cerca di capire perché un determinato codice viene compilato o meno.

Il codice utilizzato in questo articolo può essere trovato su GitHub.