Domanda

In Java, quando si esegue

int b = 0;
b = b + 1.0;

Si ottiene una possibile perdita di errore di precisione. Ma perché è che se si fa

int b = 0;
b += 1.0;

Non è un qualsiasi errore?

È stato utile?

Soluzione

Questo perché b += 1.0; equivale a b = (int) ((b) + (1.0));. I restringimento di conversione primitiva (JLS 5.1.3) è nascosto nel funzionamento assegnazione composta.

JLS 15.26. 2 Operatori di assegnazione composti (JLS Terza edizione):

  

Un'espressione assegnazione composta di modulo E1 op = E2 è equivalente a E1 = (T) ((E1) op (E2)) , dove T è il tipo di E1 , tranne che E1 viene valutata solo una volta.

     

Ad esempio, il seguente codice è corretto:

short x = 3;
x += 4.6;
     

e comporta x avente 7 valore perché equivale a:

short x = 3;
x = (short)(x + 4.6);

Questo spiega anche perché le compilazioni seguente codice:

byte b = 1;
int x = 5;
b += x; // compiles fine!

Ma questo non:

byte b = 1;
int x = 5;
b = b + x; // DOESN'T COMPILE!

È necessario lanciare in modo esplicito in questo caso:

byte b = 1;
int x = 5;
b = (byte) (b + x); // now it compiles fine!

vale la pena di notare che il cast implicito nelle assegnazioni compound è oggetto di Puzzle 9: Panco Pinco dal bellissimo libro Java Puzzlers . Ecco alcuni estratto dal libro (leggermente modificato per brevità):

  

Molti programmatori pensano che x += i; è semplicemente una scorciatoia per x = x + i;. Questo non è del tutto vero: se il tipo del risultato è più ampio di quello della variabile, l'assegnazione composto operatore esegue un silenzioso restringimento di conversione primitiva

.      

Per evitare spiacevoli sorprese, non utilizzare operatori di assegnazione composti da variabili di tipo byte, short o char. Quando si utilizzano operatori di assegnazione composti sulle variabili di tipo int, assicurarsi che l'espressione sul lato destro non è di tipo long, float o double. Quando si utilizzano operatori di assegnazione composti sulle variabili di tipo float, assicurarsi che l'espressione sul lato destro non è di tipo double. Queste regole sono sufficienti per impedire al compilatore di generare getti restringimento pericolosi.

     

Per i progettisti lingua, è probabilmente un errore per gli operatori di assegnazione composti per generare calchi invisibili; assegnamenti composti in cui la variabile ha un tipo più stretto del risultato del calcolo deve probabilmente essere illegale.

L'ultimo paragrafo è degno di nota: C # è molto più severa in proposito (vedi C # Specifiche del linguaggio 7.13.2 Compound assegnazione ).

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top