Come configurare smartphone e PC. Portale informativo

Java che converte double in int. Esempio

Ogni espressione in Java ha un tipo, che è determinato dalla struttura dell'espressione e dai tipi dei suoi operandi costituenti (costanti, variabili e metodi). Tuttavia, a volte potrebbe essere necessario convertire esplicitamente un'espressione in un altro tipo. Inoltre, in alcune situazioni, lo stesso runtime Java esegue implicitamente tali conversioni.

Tipo di conversione T 1 al tipo T 2 consente a un'espressione di tipo T 1 di essere trattata in fase di compilazione come un'espressione di tipo T 2. In alcuni casi si tratta di una costruzione puramente sintattica che non influisce sul codice generato; in altri, la conversione del tipo richiede azioni aggiuntive in fase di esecuzione per modificare il valore dell'espressione o ulteriori controlli per la correttezza della conversione applicata. Esempi:

  • Tipo di conversione int nel tipo lungo richiede un segno intero a 32 bit per espandersi in un intero a 64 bit in fase di esecuzione. In questo caso, non c'è perdita di informazioni.
  • Tipo di conversione galleggiante nel tipo lungo richiede una conversione non banale di un valore variabile a 32 bit in un numero intero a 64 bit in fase di esecuzione. La perdita di informazioni può verificarsi o meno, a seconda del valore originale.
  • La conversione da Thread a Object è semplice: poiché Thread è un discendente di Object, qualsiasi riferimento a un oggetto di tipo Thread è automaticamente un riferimento a un Object.
  • La conversione da oggetto a thread richiede la convalida in fase di esecuzione. Se il riferimento da convertire è effettivamente un riferimento a un oggetto di tipo Thread, viene restituito come risultato della conversione, altrimenti viene generata un'eccezione.

5.4.1.1. Ampliamento del numero di conversioni

Ampliamento del numero di conversioni- si tratta di conversioni di tipo numerico in tipo numerico "più grande", che sono considerate sicure, in quanto non comportano la perdita del valore del valore convertito. Tali conversioni in Java sono:

  • trasformazioni byte v breve, int, lungo, galleggiante e Doppio;
  • trasformazioni breve v int, lungo, galleggiante e Doppio;
  • trasformazioni char v int, lungo, galleggiante e Doppio;
  • trasformazioni int v lungo, galleggiante e Doppio;
  • trasformazioni lungo v galleggiante e Doppio;
  • trasformazioni galleggiante v Doppio.

Infatti, convertire un valore intero in un valore float può portare a una perdita di precisione, cioè una perdita di cifre significative. Quindi il seguente esempio

Class Test (public static void main (String args) (int bigNumber = 1234567890; float approssimativo = bigNumber; System.out.println (approssimativo);))

visualizzerà la stringa 1234567936. Ciò è dovuto al fatto che durante la conversione int v galleggiante il valore risultante è 1.2345679E9 dovuto al fatto che la mantissa dei numeri piace galleggiante ospita solo 8 cifre decimali (qui la conversione in tipo dovrebbe essere utilizzata per funzionare correttamente Doppio). Tuttavia, il sistema runtime non genera mai errori durante l'esecuzione delle trasformazioni elencate.

5.4.1.2. Restringimento del numero di conversioni

Restringimento del numero di conversioni- Si tratta di conversioni di tipo numerico in un tipo numerico "più piccolo", che può portare sia a perdita di grandezza che a perdita di precisione. Tali conversioni in Java sono:

  • trasformazioni byte v char;
  • trasformazioni breve v byte e char;
  • trasformazioni int v byte, breve e char;
  • trasformazioni lungo v byte, breve, int e char;
  • trasformazioni galleggiante v byte, breve, int, lungo e char;
  • trasformazioni Doppio v byte, breve, int, lungo, galleggiante e char;

Non considereremo qui in dettaglio le regole con cui avvengono queste trasformazioni, poiché sono intuitivamente comprensibili e formalmente piuttosto ingombranti. Quando li si utilizza è importante ricordare che Java, a differenza di altri linguaggi, non genera errori di overflow o underflow, quindi il controllo sulla correttezza delle trasformazioni ricade interamente sul programmatore.

5.4.1.3. Trasformazioni di link estensibili

Trasformazioni di link estensibili Sono conversioni di tipi di riferimento derivati ​​nei tipi dei loro antenati, che non richiedono alcuna azione in fase di esecuzione e non generano mai errori. Tali conversioni in Java sono:

  • convertire qualsiasi classe o interfaccia nel suo antenato (in particolare, nel tipo Object);
  • convertire una classe in un'interfaccia che implementa;
  • convertire qualsiasi array in tipo Object o Cloneable;
  • convertire un array di tipo S in un array di tipo T se S e T sono tipi di riferimento e la conversione da S a T si sta ampliando;
  • convertire un tipo null in qualsiasi tipo di riferimento.

5.4.1.4. Restringimento delle conversioni di link

Restringimento delle conversioni di link Sono conversioni dai tipi di riferimento derivati ​​ai relativi tipi discendenti. Queste conversioni richiedono un controllo in fase di esecuzione della loro legittimità e possono generare un'eccezione ClassCastException. Tali conversioni in Java sono:

  • convertire qualsiasi classe nel suo discendente (in particolare, convertire il tipo Object in qualsiasi altra classe);
  • convertire una classe in un'interfaccia quando la classe non è definitiva e non implementa l'interfaccia data (in particolare, convertendo il tipo Object in qualsiasi interfaccia);
  • convertire il tipo Object in qualsiasi array;
  • convertire qualsiasi interfaccia in una classe che non è definitiva;
  • convertire qualsiasi interfaccia in una classe che è finale e implementa questa interfaccia;
  • convertire l'interfaccia J nell'interfaccia K, quando J non è un discendente di K, e non esiste un metodo dichiarato sia in J che in K con la stessa firma, ma diversi tipi di risultato;
  • convertire un array di tipo S in un array di tipo T se S e T sono tipi di riferimento e la conversione da S a T si sta restringendo.

5.4.1.5. Conversioni in stringhe

Qualsiasi espressione in Java, incluso nullo, può essere convertito in String.

5.4.1.6. Conversioni non valide

Le seguenti conversioni di tipo sono vietate in Java:

  • convertire qualsiasi tipo di riferimento in qualsiasi tipo primitivo;
  • convertire qualsiasi tipo primitivo in qualsiasi tipo di riferimento diverso da String;
  • convertire il tipo zero in qualsiasi tipo primitivo;
  • conversioni al tipo null o type booleano;
  • conversioni di tipo booleano a qualsiasi altro tipo diverso dal tipo String;
  • convertire una classe in un'altra, se nessuna di esse è un antenato dell'altra (eccetto per la conversione al tipo String);
  • convertire una classe in un'interfaccia se la classe è finale e non implementa l'interfaccia data;
  • convertire una classe in un array se la classe è diversa da Object;
  • convertire un'interfaccia in una classe che è finale e non implementa l'interfaccia data (tranne per la conversione nel tipo String);
  • convertire l'interfaccia J nell'interfaccia K, se esiste un metodo dichiarato sia in J che in K con la stessa firma, ma diversi tipi di risultato;
  • convertire un array in una classe diversa da Object e String;
  • convertire un array in un'interfaccia diversa da Cloneable;
  • convertire un array di tipo S in un array di tipo T se la conversione da S a T è proibita

5.4.2. Contesti di trasformazione

5.4.2.1. Conversione su incarico

Conversione su incarico si verifica quando il valore di un'espressione viene assegnato a una variabile. Questo converte il tipo dell'espressione nel tipo della variabile. Durante l'assegnazione, sono sempre possibili conversioni di tipo allargamento (sia numeriche che di riferimento). Una conversione restrittiva è possibile solo se sono soddisfatte le seguenti condizioni:

  • la variabile è di tipo byte, breve o char;
  • il valore dell'espressione è una costante di tipo int che rientra nell'intervallo dei possibili valori della variabile.

Ad esempio, l'operatore di byte x = 123; diciamo, poiché la costante 123 (di tipo int) si trova nell'intervallo dei valori ammissibili del tipo byte.

Se il tipo dell'espressione non può essere convertito nel tipo della variabile, il compilatore genera un errore. Altrimenti si dice che il tipo dell'espressione assegnazione compatibile con un tipo variabile. Quindi, il prossimo frammento

Breve s = 123; carattere c = s; // genera un errore di compilazione

genererà un errore perché i tipi char e breve sono incompatibili nell'assegnazione secondo le definizioni di cui sopra (il primo è implementato in parole senza segno a 16 bit e il secondo - con un segno).

5.4.2.2. Argomenti del metodo di conversione

Argomenti del metodo di conversione si verifica quando i valori effettivi degli argomenti vengono convertiti nel tipo dei parametri di un metodo o costruttore quando viene chiamato. In questo caso, sono sempre possibili conversioni allargate di tipi (sia numerici che di riferimento) e non sono consentite conversioni restringenti. Le ragioni di quest'ultimo divieto possono essere spiegate dal seguente esempio:

Class Test (static int m (byte a, int b) (return a + b;) static int m (short a, short b) (return a - b;) public static void main (String args) (System.out. println ( m (1, 2)); // genera un errore di compilazione))

Qui la classe Test contiene due metodi con lo stesso nome, che differiscono solo per i tipi di parametri. Se in Java fossero consentite conversioni di argomenti restringenti, il runtime dovrebbe capire a quale di questi metodi appartiene la chiamata a m (1, 2). Per evitare tali ambiguità, gli sviluppatori del linguaggio hanno risolto radicalmente il problema: hanno vietato tali chiamate di metodo. In questa situazione, per chiamare, ad esempio, il primo metodo, dobbiamo specificare esplicitamente il tipo del primo operando (il secondo ha già il tipo predefinito int), ovvero m ((byte) 1, 2).

5.4.2.3. Conversione in stringa

Conversione in stringa si verifica solo in un caso: quando l'operazione binaria + viene applicata a due operandi, di cui uno di tipo String. In questa situazione, anche il secondo operando viene convertito nel tipo String e il risultato dell'operazione è la concatenazione delle stringhe risultanti. Questo processo è descritto più dettagliatamente nel cap. 5.14.

5.4.2.4. Conversione esplicita del tipo

Conversione esplicita del tipo si verifica quando un cast di tipo viene applicato in modo esplicito a un operando. In questa situazione, è possibile applicare tutti i tipi di conversioni di tipo sopra descritti, ad eccezione della conversione in una stringa. Un tentativo di convertire in modo esplicito in un tipo contrassegnato come proibito sopra genererà un errore di compilazione. Inoltre, è possibile che venga generata un'eccezione ClassCastException in fase di esecuzione se la conversione specificata non è valida.

5.4.3. Conversioni del tipo di operando numerico

La conversione del tipo nel processo di valutazione delle espressioni numeriche ha una serie di caratteristiche. Si riducono a due casi: conversione di operandi in operazioni unarie e in operazioni binarie.

Prima di eseguire l'operazione unaria:

  • se l'operando è di tipo byte, breve o char, si converte in type int;
  • in altri casi, il suo tipo non cambia.

Prima di eseguire un'operazione binaria:

  • se uno degli operandi è di tipo Doppio, quindi anche il secondo viene convertito in type Doppio;
  • galleggiante, quindi anche il secondo viene convertito in type galleggiante;
  • altrimenti, se uno degli operandi è di tipo lungo, quindi anche il secondo viene convertito in type lungo;
  • in caso contrario, entrambi gli operandi vengono convertiti in type int.

Questo è un argomento abbastanza ampio, ma cercheremo di considerarlo nel modo più completo possibile e allo stesso tempo in modo compatto. Abbiamo già toccato in parte questo argomento quando abbiamo esaminato i tipi primitivi di Java.

Le conversioni tra valori interi e in virgola mobile sono possibili in Java. Inoltre, puoi convertire i valori interi e in virgola mobile in valori di caratteri e viceversa, poiché ogni carattere corrisponde a una cifra Unicode. In effetti, il tipo booleano è l'unico tipo primitivo in Java che non può essere convertito in un altro tipo primitivo. Inoltre, nessun altro tipo primitivo non può essere convertito in booleano.

Esistono due tipi di conversioni in Java: implicito e esplicito.

Conversione implicita del tipo viene eseguita se sono soddisfatte le seguenti condizioni:

  1. Entrambi i tipi sono compatibili
  2. La lunghezza del tipo di destinazione è maggiore o uguale alla lunghezza del tipo di origine

In tutti gli altri casi, dovrebbe essere usato conversione di tipo esplicita.

Esistono anche due tipi di trasformazioni:

  1. Ampliamento della conversione
  2. Conversione restrittiva

Trasformata allargante ( ampliando la conversione) si verifica quando un valore dello stesso tipo viene convertito in un tipo più ampio con un intervallo più ampio di valori validi. Java esegue automaticamente le conversioni di ampliamento, ad esempio, se assegni un int literal a un double o un char invariato a un int. La conversione implicita è sempre un tipo di ampliamento.

Ma qui può avere i suoi piccoli rastrelli. Ad esempio, se converti un valore int in un valore float. E il valore int nella rappresentazione binaria ha più di 23 bit significativi, quindi la perdita di precisione è possibile, poiché il tipo float ha 23 bit allocati per la parte intera. Tutti gli LSB int i valori che non rientrano nei 23 bit della mantissa float verranno scartati, quindi sebbene l'ordine dei numeri venga preservato, la precisione andrà persa. Lo stesso vale per la conversione da long a double.

L'ampliamento della conversione del tipo Java può anche essere rappresentato in questo modo:

Le linee continue rappresentano le conversioni senza perdita di dati. Le linee tratteggiate indicano una perdita di precisione durante la conversione.

Vale la pena spiegare un po' perché, ad esempio, il tipo byte non viene convertito automaticamente (non esplicitamente) nel tipo char, sebbene il tipo byte sia largo 8 bit e il char sia 16, lo stesso vale per la conversione di short carbonizzare. Questo perché byte e short sono tipi di dati con segno, mentre char è senza segno. Pertanto, in questo caso, è necessario utilizzare il casting esplicito, poiché il compilatore deve indicare esplicitamente che si conosce ciò che si desidera e come verranno elaborati il ​​bit di segno dei tipi byte e short durante la conversione nel tipo char.

Nella maggior parte dei casi, il comportamento di un valore char è lo stesso di quello di un valore intero; pertanto, un valore char può essere utilizzato ovunque siano richiesti valori int o long. Ricordiamo però che char è unsigned, quindi si comporta diversamente da short, anche se l'intervallo di entrambi i tipi è di 16 bit.

breve S = ( breve ) 0xffff; // Questi bit rappresentano il numero -1
char C = "\uffff"; // Gli stessi bit rappresentano il carattere unicode
int i1 = S; // La conversione di short in int dà -1
int i2 = C; // La conversione di char in int dà 65535

Restringimento trasformazione ( restringendo la conversione) si verifica quando un valore viene convertito in un valore di un tipo il cui intervallo non è più ampio dell'originale. Le conversioni di restringimento non sono sempre sicure: ad esempio, convertire un valore intero 13 in un byte ha senso, ma convertire 13000 in un byte non è saggio, poiché il byte può memorizzare solo numeri da -128 a 127. Poiché i dati possono essere persi durante un restringimento conversione, il compilatore Java si oppone a tale conversione, anche se il valore da convertire rientra nell'intervallo più ristretto del tipo specificato:

int io = 13 ;
byte B = io ; // Il compilatore non risolverà questa espressione

L'unica eccezione a questa regola è l'assegnazione di un valore letterale intero (valore int) a una variabile di byte, o short se il letterale corrisponde all'intervallo della variabile.

Le conversioni restrittive sono sempre conversioni esplicite..

Conversione esplicita di tipi primitivi

L'operatore di conversione di tipo esplicito o, più precisamente, conversioni di tipo sono parentesi, all'interno delle quali è indicato il tipo a cui viene eseguita la conversione - (genere)... Ad esempio:

int io = 13 ;
byte B = ( byte ) io ; // Conversione forzata di int in byte
io = ( int ) 13.456 ; // Conversione forzata di un letterale di tipo double in int 13

Il casting di tipi primitivi è più spesso usato per convertire i valori in virgola mobile in numeri interi... in cui la parte frazionaria del valore in virgola mobile viene semplicemente scartata(ovvero, il valore in virgola mobile viene arrotondato verso lo zero anziché l'intero più vicino). Essenzialmente viene presa solo la parte intera del tipo reale ed è già stato eseguito il cast al tipo intero di destinazione.

Quando si porta un più capiente tipo intero a bit di ordine superiore meno capienti vengono semplicemente scartati... In sostanza, questo è equivalente all'operazione di modulo il valore che deve essere lanciato dall'intervallo del tipo di destinazione (ad esempio, per il tipo di byte, è 256).

Un numero frazionario troppo grande quando viene convertito in intero diventa MAX_VALUE o MIN_VALUE.

Troppo grande Doppio quando ridotto a galleggiante diventa Float.POSITIVE_INFINITY o Float.NEGATIVE_INFINITY.

La tabella sottostante è una griglia dove, per ogni tipo primitivo, sono indicati i tipi in cui possono essere convertiti e il metodo di conversione. Lettera n nella tabella indica l'impossibilità di conversione. Lettera significa una conversione allargata che viene eseguita automaticamente. Lettera CON indica una conversione restrittiva che richiede un cast esplicito. Infine, Sì * indica una conversione ad allargamento automatico, durante la quale il valore può perdere alcune delle cifre meno significative. Questo può accadere quando si converte int o long in float o double. I tipi a virgola mobile hanno un intervallo più ampio rispetto ai tipi interi, quindi int o long possono essere rappresentati come float o double. Tuttavia, i tipi in virgola mobile sono numeri approssimativi e potrebbero non contenere sempre tanti bit significativi nella mantissa quanti tipi interi.

Espansione automatica del tipo nelle espressioni

Vale anche la pena menzionare la promozione (espansione) automatica dei tipi nelle espressioni. Lo abbiamo già riscontrato quando abbiamo considerato i tipi di dati interi e le operazioni su di essi, ma vale comunque la pena ricordarlo qui per renderlo ancora migliore e, inoltre, è direttamente correlato a questo argomento. Nell'esempio sotto, il segno @ + , , * , / eccetera.

Cioè, tutti i letterali interi nelle espressioni, così come i tipi byte, breve e char espandere a int ... Se, come descritto sopra, nessun altro tipo di dati più grande ( lungo, galleggiante o Doppio). Pertanto, l'esempio precedente genererà un errore di compilazione come variabile Cè di tipo byte, e l'espressione b + 1, per effetto della promozione automatica, ha il tipo int.

Coercizione implicita nelle espressioni di co-assegnazione

Sebbene questa sezione si riferisca alla conversione implicita (casting) dei tipi, ne abbiamo fornita la spiegazione qui, poiché in questo caso funziona anche l'espansione automatica dei tipi nelle espressioni e quindi il casting implicito dei tipi. Ecco un corpo di ballo. L'esempio qui sotto, credo, chiarirà tutto. Come nella spiegazione precedente, il segno @ indica qualsiasi operatore valido, ad esempio + , , * , / eccetera.

Vale la pena spiegarlo con un semplice esempio:

byte b2 = 50 ;
b2 = b2 * 2 ; // non compilerà
b2 *= 2 ; // compilerà, sebbene sia equivalente a b2 = b2 * 2

La seconda riga mostrata nell'esempio non verrà compilata a causa dell'espansione automatica del tipo nelle espressioni, poiché l'espressione b2 * 2 è di tipo int, poiché esiste un'espansione automatica del tipo (i letterali interi nell'espressione sono sempre int). La terza riga sarà facile da compilare, dal momento che il typecasting implicito nell'espressione di assegnazione combinata funzionerà in essa.

Boxing / unboxing - conversione di tipi primitivi in ​​oggetti wrapper

Anche il pugilato e l'unboxin sono argomenti piuttosto vasti, ma sono abbastanza semplici.

Essenzialmente boxing e unboxing sono tipi primitivi da e verso oggetti wrapper.

Per oggetti di wrapper di tipo primitivo vale tutto quanto detto sopra.

Le classi wrapper sono state menzionate nelle tabelle durante l'analisi di ciascuno dei tipi primitivi. Ma poi era solo una menzione nella tabella.

Quindi, per ogni tipo primitivo c'è il suo fratello maggiore, e non è affatto primitivo, ma è una vera e propria classe, con campi e metodi. E per ciascuna di queste coppie, è possibile la conversione automatica.

Di solito, se il programma ha molti calcoli matematici, allora è meglio usare tipi primitivi, poiché è più veloce ed economico in termini di risorse, ma a volte è necessario convertire un tipo primitivo in un oggetto.

Ti faccio un semplice esempio:

int i3 ;
byte b2 = 3 ;
Byte mioB ;
mioB= b2;
mioB++;
b2= mioB;
i3= mioB;

Se non è ancora chiaro il motivo per cui è necessario, allora non è spaventoso, basta fare un nodo come ricordo.

L'oratore precedente ha descritto in modo abbastanza completo la trasformazione dall'alto verso il basso, ma quella dal basso verso l'alto (secondo me) richiede ulteriori spiegazioni, poiché la domanda è molto popolare e interessante.

Come funziona il casting esplicito?

Il tuo esempio mostra una conversione verso l'alto ( Upcasting):

Lista coll = new ArrayList ();

Si traduce in russo come segue: crea un corvo, come un uccello. Crea un array dinamico come un foglio. Nella maggior parte delle situazioni, una conversione verso l'alto è completamente inutile.
Tuttavia, il casting funziona nelle interviste quando ti vengono poste domande sull'eredità. Ad esempio, il sito quizful.net contiene generalmente molte domande sul typecasting. Pertanto, spiegherò le caratteristiche che conosco.

Quindi, nell'esempio sopra, abbiamo creato un oggetto di tipo ArrayList e un riferimento di tipo List. Ricorda gli assiomi per questo metodo:

1. Il collegamento può puntare a qualsiasi genitore. Anche molto tempo fa. Cioè, puoi lanciare coll anche per digitare Object. Il compilatore salterà qualsiasi riferimento alla classe del genitore, o genitore-genitore, o genitore-genitore ... genitore

2. Riferito al campo: viene sempre restituito il campo di riferimento, non il campo dell'oggetto. Se non esiste un campo di questo tipo nella classe di riferimento, si verificherà un errore di compilazione.

Classe A (int x = 2; // Campo del genitore) La classe B estende A (int x = 3; // Campo che dovrebbe sovrapporsi al genitore int y = 5; // Campo che non è nella classe genitore.) Class Test (public static void main (String args) (A ab = new B (); // Conversione verso l'alto System.out.println ("Int x =" + ab.x);))

Sarà di ritorno Int x = 2 ... Se provi ad accedere a un campo oggetto:

System.out.println ("Int y =" + ab.y); // Errore di compilazione

Il tuo compilatore dirà che ti sbagli, poiché non vede un tale campo per riferimento (A ab). Tutto quanto sopra rimane valido anche se i tuoi campi sono contrassegnati con modificatori statici.

3. Chiamare un metodo non statico: in questo caso, restituirà il metodo dell'oggetto. Ma quando si accede a un metodo statico, restituisce il metodo di riferimento.

Classe D (public void doSome () (// Metodo non statico System.out.println ("Nonstatic doSome da D");) public static void Action () (// Metodo statico System.out.println ("Azione statica da D" ");)) public class Okey estende D (public void doSome() (System.out.println (" doSome da Okey ");) public static void Action () (System.out.println (" static Action from Okey " );) public static void main (String args) (D o = new Okey (); o.doSome (); // Dalla classe Okey o.Action (); // Dalla classe D))

DoSome non statico da Okey

Azione statica da D

La risposta è semplice, un metodo non statico è un metodo oggetto, un metodo statico è un metodo di classe. Quando chiamiamo un metodo non statico, il compilatore lo capisce: vola come un corvo. Quando chiamiamo statico - letteralmente, vola come un uccello.

4. Se è presente una chiamata a un metodo descritto nella classe dell'oggetto, ma non descritto nella classe di riferimento, si verificherà un errore di compilazione. Perché, il metodo viene chiamato per riferimento:

Classe A () La classe B estende A (void someMethod () (); public static void main (String args) (A ab = new B (); ab.someMethod (); // Errore di compilazione.))

5. Il costruttore di un oggetto (quando viene creato con il nuovo comando) funziona come se si fornisse un riferimento alla propria classe.

A volte ci sono situazioni in cui hai un valore di un certo tipo e devi assegnarlo a una variabile di un tipo diverso. Per alcuni tipi, questo può essere fatto senza conversione del tipo, in questi casi si parla di conversione automatica del tipo. In Java, la conversione automatica è possibile solo se la precisione della variabile di destinazione è sufficiente per memorizzare il valore originale. Tale conversione si verifica, ad esempio, quando una costante letterale o il valore di una variabile di tipo byte o short viene immessa in una variabile di tipo int. È chiamato estensione (allargando) o aumento (promozione), poiché un tipo con una profondità di bit inferiore viene espanso (ridimensionato) in un tipo compatibile più grande. La dimensione del tipo int è sempre sufficiente per memorizzare i numeri nell'intervallo consentito per il tipo byte, quindi, in tali situazioni, non è richiesto un operatore di cast esplicito. Il contrario non è vero nella maggior parte dei casi, quindi è necessario utilizzare l'operatore cast per eseguire il cast di un valore int in una variabile di byte. Questa procedura è talvolta chiamata restringimento (restringimento), perché stai dicendo esplicitamente al traduttore di convertire il valore per adattarlo a una variabile del tipo che desideri. Per eseguire il cast di un valore su un tipo specifico, è necessario specificare questo tipo, racchiuso tra parentesi, prima di esso. Il seguente frammento di codice mostra il casting da un'origine (variabile di tipo int) al tipo di destinazione (variabile di tipo byte). Se durante tale operazione il valore intero uscisse dall'intervallo consentito per il tipo di byte, verrebbe ridotto dividendo modulo per l'intervallo consentito per byte (il risultato della divisione modulo per un numero è il resto della divisione per questo numero) ,

int a = 100;
byteb = (byte) a;

2.2.1. Conversione automatica del tipo nelle espressioni

Quando si valuta il valore di un'espressione, la precisione richiesta per memorizzare i risultati intermedi spesso deve essere superiore a quella richiesta per rappresentare il risultato finale,

byte a = 40;
byte b = 50;
byte con = 100;
int d = a * b / s;

Il risultato dell'espressione intermedia (a * b) potrebbe andare al di fuori dell'intervallo di valori consentito per il tipo di byte. Questo è il motivo per cui Java promuove automaticamente ogni parte dell'espressione a int, quindi c'è spazio sufficiente per il risultato intermedio (a * b).

La conversione automatica del tipo a volte può causare messaggi di errore imprevisti del traduttore. Ad esempio, il codice mostrato di seguito, sebbene appaia abbastanza corretto, genera un messaggio di errore durante la fase di traduzione. In esso, stiamo cercando di scrivere il valore 50 * 2, che dovrebbe adattarsi perfettamente al tipo di byte, in una variabile di byte. Ma a causa della conversione automatica del tipo di risultato in int, riceviamo un messaggio di errore dal traduttore - dopo tutto, quando int viene inserito in byte, può verificarsi una perdita di precisione.

byte b = 50;
b = b * 2:
^ Tipo incompatibile per =. Cast esplicito necessario per convertire int in byte.
(Tipo incompatibile per =. Conversione esplicita richiestaint inbyte)

Testo corretto:
byteb = 50;
b = (byte) (b*2);

che fa sì che b inserisca il valore corretto di 100.

Se un'espressione utilizza variabili di tipo byte, short e int, il tipo dell'intera espressione viene automaticamente promosso a int per evitare l'overflow. Se il tipo di almeno una variabile nell'espressione è long, anche il tipo dell'intera espressione viene promosso a long. Ricorda che tutti i letterali interi che non terminano con una L (o 1) sono int.

Se l'espressione contiene operandi di tipo float, il tipo dell'intera espressione viene automaticamente promosso a float. Se almeno uno degli operandi è di tipo double, il tipo dell'intera espressione viene promosso a double. Per impostazione predefinita, Java tratta tutti i valori letterali in virgola mobile come doppi. Il programma seguente mostra come viene promosso il tipo di ogni valore nell'espressione in modo che corrisponda al secondo operando di ogni operatore binario.

classe promuovere (
public static void main (String args) (
byte b = 42;
carattere con= "un";
pantaloncini = 1024;
int i = 50000;
float f = 5.67f;
raddoppiato = 0,1234;
doppio risultato = (f * b) + (i / c) - (d * s);
Sistema, fuori. println ((f * b) + "+" + (i / c) + "-" + (d * s));
Sistema, fuori. println ("risultato =" + risultato); )
}

La sottoespressione f * b è un float moltiplicato per un byte, quindi viene automaticamente promosso a float. La seguente sottoespressione i / c (int diviso per char) viene promossa a int. Allo stesso modo, il tipo della sottoespressione d * s (doppio per breve) viene promosso a doppio. Nella fase successiva dei calcoli, ci occupiamo di tre risultati intermedi di tipo float, int e double. Innanzitutto, quando i primi due vengono sommati, il tipo int viene promosso a float e il risultato è un tipo float. Quando viene sottratto un valore double, il tipo di risultato viene promosso a double. Il risultato finale dell'intera espressione è un doppio.

Ora che abbiamo familiarità con tutti i tipi semplici, inclusi numeri interi e reali, simboli e variabili booleane, proviamo a mettere insieme tutte le informazioni. L'esempio seguente crea variabili di ciascuno dei tipi semplici e restituisce i valori di tali variabili.

classe SimpleTypes (
public static void main (String args) (
byte b = 0x55;
breve s = 0x55ff;
int i = 1000000;
lungo l = 0xffffffffL;
carattere con= 'A';
float f = .25f;
doppia d = .00001234;
booleano bool = vero;
System.out.println ("byte b =" + b);
System.out.println ("breve s =" + s);
System.out.println ("int i =" + i);
System.out.println ("long 1 =" + l);
System.out.println ("carattere con= ”+ S);
System.out.println ("float f =" + f);
System.out.println ("doppia d =" + d);
System.out.println ("boolean bool =" + bool);)
}

Eseguendo questo programma, dovresti ottenere il risultato mostrato di seguito:

byte b = 85
pantaloncini = 22015
int i = 1000000
lungo 1 = 4294967295
carattere con= a
flottante f = 0,25
doppia d = 1.234e-005
booleano bool = vero

Nota che gli interi vengono stampati in notazione decimale, sebbene abbiamo specificato i valori per alcuni di essi in notazione esadecimale.

Ultimo aggiornamento: 29/10/2018

Ciascun tipo di dati di base occupa un certo numero di byte di memoria. Ciò pone una restrizione alle operazioni che coinvolgono diversi tipi di dati. Considera il seguente esempio:

Int a = 4; byte b = a; //! Errore

In questo codice, incontreremo un errore. Sebbene sia byte che int rappresentino numeri interi. Inoltre, il valore della variabile a, che è assegnata a una variabile di tipo byte, rientra ampiamente nell'intervallo di valori per il tipo di byte (da -128 a 127). Tuttavia, ci imbattiamo in un errore in fase di compilazione. Perché in questo caso stiamo cercando di assegnare alcuni dati di 4 byte a una variabile di solo 1 byte.

Tuttavia, il tuo programma potrebbe dover eseguire questa conversione. In questo caso, devo utilizzare l'operazione di conversione del tipo (operazione ()):

Int a = 4; byte b = (byte) a; // conversione del tipo: da int a byte System.out.println (b); // 4

L'operazione di conversione del tipo implica un'indicazione tra parentesi del tipo in cui convertire il valore. Ad esempio, nel caso di un'operazione (byte), il tipo di dati int viene convertito nel tipo di byte. Di conseguenza, otteniamo un valore in byte.

Conversioni esplicite e implicite

Quando dati di tipo diverso sono coinvolti nella stessa operazione, non è sempre necessario utilizzare un'operazione di conversione del tipo. Alcuni tipi di conversioni vengono eseguiti implicitamente, automaticamente.

Conversioni automatiche

Le frecce nella figura mostrano quali conversioni di tipo possono essere eseguite automaticamente. Le frecce tratteggiate mostrano le conversioni automatiche con perdita di precisione.

Prodotto automaticamente senza alcun problema trasformazioni allarganti(allargamento) - espandono la rappresentazione di un oggetto in memoria. Ad esempio:

Byte b = 7; int d = b; // converte da byte a int

In questo caso, un byte, che occupa 1 byte in memoria, viene espanso in un int, che occupa 4 byte.

Le trasformazioni automatiche in espansione sono rappresentate dalle seguenti catene:

byte -> breve -> int -> lungo

int -> double

breve -> float -> double

char -> int

Conversioni automatiche con perdita di precisione

Alcune conversioni possono essere eseguite automaticamente tra tipi di dati con la stessa profondità di bit o anche da un tipo di dati con una profondità di bit maggiore a un tipo con una profondità di bit inferiore. Queste sono le seguenti catene di conversioni: int -> float, long -> float e long -> double vengono eseguite senza errori, ma potremmo riscontrare una perdita di informazioni durante la conversione.

Ad esempio:

Int a = 2147483647; galleggiante b = a; // da int a float System.out.println (b); // 2.14748365E9

Conversioni esplicite

Tutte le altre conversioni di tipo primitivo applicano in modo esplicito la definizione di conversione di tipo. Di solito, si tratta di restringere le conversioni da un tipo con una profondità di bit maggiore a un tipo con una profondità di bit inferiore:

Lungo a = 4; int b = (int) a;

Perdita di dati durante la conversione

Quando si utilizzano trasformazioni esplicite, potremmo riscontrare la perdita di dati. Ad esempio, con il seguente codice, non avremo problemi:

Int a = 5; byte b = (byte) a; System.out.println (b); // 5

Il numero 5 si adatta bene all'intervallo di valori del tipo di byte, quindi dopo la conversione la variabile b sarà 5. Ma cosa succede nel caso seguente:

Int a = 258; byte b = (byte) a; System.out.println (b); // 2

Il risultato è 2. In questo caso, 258 è fuori dall'intervallo per il byte (da -128 a 127), quindi il valore verrà troncato. Perché il risultato è esattamente il numero 2?

Il numero a, che è 258, in binario sarà 00000000 00000000 00000001 00000010. I valori dei byte occupano solo 8 bit in memoria. Pertanto, la rappresentazione binaria di int viene troncata alle 8 cifre giuste, ovvero 00000010, che fornisce 2 in decimale.

Troncare i numeri razionali a numeri interi

Quando si convertono valori in virgola mobile in valori interi, la parte frazionaria viene troncata:

Doppio a = 56,9898; int b = (int) a;

Qui b sarebbe 56, anche se 57 sarebbe più vicino a 56,9898. Per evitare tali incidenti, è necessario utilizzare la funzione di arrotondamento, che si trova nella libreria matematica Java:

Doppio a = 56,9898; int b = (int) Math.round (a);

Trasformazioni nelle operazioni

Ci sono spesso situazioni in cui devi applicare varie operazioni, ad esempio addizione e prodotto, su valori di tipo diverso. Alcune regole si applicano anche qui:

    se uno degli operandi dell'operazione è di tipo double, anche il secondo operando viene convertito nel tipo double

    se la condizione precedente non è soddisfatta e uno degli operandi dell'operazione è di tipo float, anche il secondo operando viene convertito nel tipo float

    se le condizioni precedenti non sono soddisfatte, uno degli operandi dell'operazione è di tipo long, quindi anche il secondo operando viene convertito in tipo long

    in caso contrario, tutti gli operandi dell'operazione vengono convertiti nel tipo int

Esempi di trasformazioni:

Int a = 3; doppia b = 4,6; doppia c = a + b;

Poiché l'operazione prevede un valore double, viene eseguito il cast dell'altro valore sul tipo double e la somma dei due valori a + b rappresenterà il tipo double.

Un altro esempio:

Byte a = 3; breve b = 4; byte c = (byte) (a + b);

Le due variabili sono di tipo byte e short (non double, float o long), quindi vengono convertite in int quando vengono aggiunte e la loro somma a + b rappresenta un int. Pertanto, se assegniamo questa somma a una variabile di tipo byte, dobbiamo nuovamente eseguire una conversione di tipo in byte.

Se le operazioni coinvolgono dati di tipo char, vengono convertite in int:

Int d = "a" + 5; System.out.println (d); //102

Principali articoli correlati