Domanda

Al mio shock, si scopre che il seguente codice compilerà senza nemmeno avvertimenti:

public void test()
{
    int value = 2000000000;
    long increment = 1000000000;
    value += increment;
}
.

considerando che questo fornisce un errore di compilazione, come ci si aspetterebbe:

public void test()
{
    int value = 2000000000;
    long increment = 1000000000;
    value = value + increment;
}
.

L'ho controllato e in effetti, il JLS (Sezione 15.26.2) ha questo da dire:

.

Un'espressione di assegnazione composta del modulo E1 OP= E2 è equivalente a E1= (T) ((E1) OP (E2)), in cui T è il tipo di E1, tranne che E1 viene valutato solo una volta.

Questo sembra ridicolo per me.Perché hanno sentito il bisogno di lanciare esplicitamente qui?Sembra che la conversione automatica del tipo avrebbe gestito l'allargamento comunque e riducendo automaticamente così come questo è praticamente garantito nel determinare un overflow intero.

È stato utile?

Soluzione

qui è unoSpiegazione:

.

Quando si esegue un incarico (il primo frammento di codice), Java impone il controllo del tipo perché il LHS e il RHS possono benissimo essere indipendente l'uno dall'altro.

Ma l'operatore composto è più simile un operatore incrementale.Il +=. modifica il valore della variabile coinvolto, piuttosto che assegnare un nuovo Valore alla variabile.Quando modificati Un byte, ti aspetti un byte come il risultato.Per rendere la vita più facile, Java fa una conversione di tipo implicita per operatori composti perché sono Modificatori.

Altri suggerimenti

Gli operatori di assegnazione composti sono specificati dal JLS ( 15.26.2 ) come segue:

.

"Un'espressione di assegnazione composta del modulo E1 op= E2 è equivalente a

      E1 = (T)((E1) op (E2))`, 
.

.

dove t è il tipo di E1, tranne che E1 viene valutato solo una volta. "

In questo caso E1 è di tipo int E2 è di tipo long, e OP è +. Quindi questo è equivalente a:

value = (int)(value + increment);
.

L'aggiunta di un int e un long fornisce un long che viene quindi tornato a un int prima dell'assegnazione. Va tutto bene, quindi nessun errore di compilazione.

La differenza tra questo e il semplice assegnazione (I.e. value = value + increment;), è che il semplice incarico non ha un typecast.


.

OK, quindi perché lo definiscono in questo modo?

Penso che il motivo sia di fare esempi come questo lavoro:

    byte b = ...
    b += 1;
.

Senza il typecast, b += 1 sarebbe un errore di compilazione e dovresti scriverlo come:

    b += (byte) 1;
.

Questo link ha analizzato il problema che hai portato.

comportamento variabile per la possibile perdita di precisione

.

per evitare spiacevoli sorprese, non farlo Utilizzare gli operatori di assegnazione composti su Variabili di tipo byte, breve o char.Quando si utilizza l'assegnazione composta Operatori su variabili di tipo int, Assicurati che l'espressione sul il lato destro non è di tipo lungo, galleggiare o doppio.Quando si usa il composto Operatori di assegnazione sulle variabili di Tipo galleggiante, assicurati che l'espressione sul lato destro non è di tipo Doppio.Queste regole sono sufficienti per impedire il generare il compilatore Cast di restringimento pericolosi.

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