2012-01-31 13 views
10

Considerate questa funzione:L'ordine delle operazioni da sinistra a destra è garantito in Java?

public static final int F(int a, int b) { 
    a = a - 1 + b; 
    // and some stuff 
    return a; 
} 

è E 'necessario per le implementazioni di JVM da eseguire prima di - 1+ b?

Se abbiamo un profiler di sistema collegato alla JVM, vedremo l'operazione + b eseguita prima dell'operazione + 1?

+0

Non è rilevante, ma che cos'è 'input'? –

+0

@SoboLAN un errore di battitura .. – Pacerier

+1

@Pacerier - questo non è un [breve, autonomo, corretto (compilabile), esempio] (http://sscce.org). Non è autonomo (non esiste alcuna delcaricazione di classe, né principale). Non è compilabile (conteneva un refuso - lo hai copiato e incollato?). –

risposta

6

in realtà, io in disaccordo con il resto delle risposte. Il JLS §15.7 a cui le persone si riferiscono fa riferimento alla valutazione degli operandi. Cioè, nell'espressione

x = foo() - 1 + bar() 

, in cui verrà richiamato il metodo.

La sezione rilevante è §15.7.3, che specifica

Un'implementazione non possono usufruire delle identità algebriche come la legge associativa per riscrivere le espressioni in una più conveniente ordine computazionale a meno che può essere provato che l'espressione sostituzione è equivalente in valore ed effetti collaterali osservabili [...]

da th L'espressione x = x - 1 + q è equivalente in tutti i modi a x = x + q - 1, un'implementazione conforme è autorizzata a riscrivere l'espressione (se per qualche motivo dovrebbe decidere che è più efficiente).

+0

@Pacerier, prendere la seguente nota. In generale, 'foo()' può influenzare 'bar()', quindi JVM dovrebbe onorare l'ordine. Lo stesso per 'i> 0 && x/i> 3'. Algebricamente, 'a && b' è equivalente a' b && a', ma avendo 'i> 0' prima evita un NPE nella seconda espressione. – rdllopes

2

Secondo here:

operatori sulla stessa riga hanno uguale precedenza. Quando gli operatori di uguale priorità appaiono nella stessa espressione, una regola deve governare che viene valutata per prima. Tutti gli operatori binari ad eccezione degli operatori di assegnazione vengono valutati da sinistra a destra; assegnazione operatori sono valutati da destra a sinistra.

Quindi sì.

2

Sì, anche se la domanda più importante è davvero importante? La sottrazione e l'aggiunta hanno la stessa precedenza in qualsiasi operazione matematica scientifica e sono commutabili. Ovvero:

x = input - 1 + q;

è uguale

x = ingresso + q - 1;

+0

Voglio dire che non mi piace quando trabocca, ma pensandoci anche se trabocca, il risultato è lo stesso .. – Pacerier

+0

Vero, ma in entrambi i casi è possibile che si verifichi l'overflow, ovvero se l'input è MIN_INTEGER o q + input = MAX_INTEGER. Non esiste un modo reale per proteggersi da questo nel tuo esempio. –

1

Sì lo sarà sempre, anche se non inciderebbe il risultato della somma/sottraendo comunque.

7

Sì, è in linguaggio Java specification, §15.7.

Il linguaggio di programmazione Java garantisce che gli operandi degli operatori sembrano essere valutati in un ordine di valutazione specifico, vale a dire da sinistra a destra.

Si consiglia di non basare il codice su queste specifiche. Il codice è in genere più chiaro quando ciascuna espressione contiene al massimo un effetto collaterale, come la sua operazione più esterna, e quando il codice non dipende esattamente da quale eccezione si presenta come conseguenza della valutazione delle espressioni da sinistra a destra.

+0

"Sembra essere valutato" - Java ha una regola "as-if", simile agli standard C e C++? Vale a dire che la JVM è autorizzata a fare tutto ciò che vuole, a patto che ciò non sia indistinguibile dal comportamento dello standard? –

+2

@Rob Sì, lo fa. Può eseguire operazioni in qualsiasi ordine che appare * nel thread in esecuzione * come se fossero eseguite nell'ordine specificato. Dal punto di vista degli altri thread, tuttavia, possono sembrare che si verifichino fuori ordine. Ecco perché più thread devono coordinarsi utilizzando barriere di memoria ben definite. – erickson

1

In realtà non sarebbe l'implementazione della JVM che conta, dal momento che eseguono solo un elenco di istruzioni dal file di classe.

2

È possibile vedere qui la precedenza degli operatori in Java: http://bmanolov.free.fr/javaoperators.php.Poiché + e - hanno la stessa precedenza, verranno eseguiti nell'ordine in cui appaiono.

Se si vuole essere più chiari su ciò che il funzionamento avviene prima (o se si vuole rompere il built-in precedenza) parantheses, si può (e dovrebbe) utilizzare (( e )), in questo modo:

x = (a - b) + (c * (d - e))

1

Mi sembra ci sarà sempre un effetto collaterale di eseguire X + q - 1 Quando si deve essere in esecuzione X - 1 + q.

Quando la somma x + q supera Bignum di 1, l'esecuzione da sinistra a destra avrà esito positivo ... L'esecuzione fuori servizio genererà un overflow.

Quindi l'esecuzione fuori servizio ha un effetto collaterale.

A meno che i trap di esecuzione fuori ordine non si sovrappongano, quindi si esegue il calcolo nell'ordine corretto quando necessario per evitare l'effetto collaterale.

0

Importante aggiungere qui è che java ha in linea la precedenza per gli operatori che sembra essere basato sull'ordine aritmetico di base delle operazioni. Per un elenco di precedenza completa guarda questo source