Domanda

ho una lunga serie di confronti da fare in Java, e mi piacerebbe sapere se uno o più di loro vengono fuori come vero. La stringa di confronti è stata lunga e difficile da leggere, così ho rotto in su per la leggibilità, e automaticamente è andato a utilizzare un operatore di |= scorciatoia piuttosto che negativeValue = negativeValue || boolean.

boolean negativeValue = false;
negativeValue |= (defaultStock < 0);
negativeValue |= (defaultWholesale < 0);
negativeValue |= (defaultRetail < 0);
negativeValue |= (defaultDelivery < 0);

Mi aspetto negativeValue per essere vero se qualcuno di default valori sono negativi. È questo è valido? Farà quello che mi aspetto? Non ho potuto vedere menzionato sul sito del Sole o StackOverflow, ma Eclipse non sembra avere un problema con esso e il codice compilato ed eseguito.


Allo stesso modo, se volevo eseguire diverse intersezioni logiche, potrei usare &= al posto di &&?

È stato utile?

Soluzione

Il |= è un operatore di assegnazione composto ( JLS 15.26.2 ) per il booleano | operatore logico ( JLS 15.22.2 ); da non confondere con il ( JLS 15.24 ). Ci sono anche &= e ^= corrispondente alla versione assegnazione composto della & logica booleana e ^ rispettivamente.

In altre parole, per boolean b1, b2, questi due sono equivalenti:

 b1 |= b2;
 b1 = b1 | b2;

La differenza tra gli operatori logici (& e |) rispetto alle loro controparti condizionali (&& e ||) è che il primo non "corto circuito"; questi ultimi fanno. Cioè:

  • & e | sempre valutare sia gli operandi
  • && e || valutare l'operando di destra condizionalmente ; l'operando di destra viene valutata solo se il suo valore potrebbe compromettere il risultato dell'operazione binaria. Ciò significa che l'operando di destra non viene valutato quando:
    • L'operando a sinistra di && restituisce false
      • (perché non importa quale sia l'operando di destra restituisce, l'intera espressione è false)
    • L'operando a sinistra di || restituisce true
      • (perché non importa quale sia l'operando di destra restituisce, l'intera espressione è true)

Quindi, tornando alla tua domanda iniziale, sì, che costrutto è valida, e mentre |= non è esattamente un collegamento equivalente per = e ||, lo fa calcolare ciò che si desidera. Dal momento che il lato destro dell'operatore |= nel vostro uso è una semplice operazione di confronto intero, il fatto che non | cortocircuito è insignificante.

Ci sono casi, quando corto circuiti è desiderato, o addirittura necessario, ma lo scenario non è uno di loro.

E 'un peccato che a differenza di altri linguaggi, Java non ha &&= e ||=. Questo è stato discusso nella questione Perché non Java ha versioni di assegnazione composti degli operatori condizionali e condizionali e-o? (&& =, || =) .

Altri suggerimenti

Non è una "scorciatoia" (o corto circuito) operatore in modo che || e && sono (nel senso che non valuteranno la RHS se sanno già il risultato in base alla LHS) ma lo farà quello che vuoi in termini di lavoro .

Come esempio della differenza, questo codice sarà bene se text è nullo:

boolean nullOrEmpty = text == null || text.equals("")

che tale non:

boolean nullOrEmpty = false;
nullOrEmpty |= text == null;
nullOrEmpty |= text.equals(""); // Throws exception if text is null

(Ovviamente si potrebbe fare "".equals(text) per quel caso specifico -. Sto solo cercando di dimostrare il principio)

Si potrebbe semplicemente avere una dichiarazione. Espressa su più righe si legge quasi esattamente come il vostro codice di esempio, solo meno imperativo:

boolean negativeValue
    = defaultStock < 0 
    | defaultWholesale < 0
    | defaultRetail < 0
    | defaultDelivery < 0;

Per le espressioni più semplici, utilizzando | può essere più veloce di || perché, anche se si evita di fare un confronto significa utilizzare un ramo implicitamente e che può essere molte volte più costoso.

Anche se potrebbe essere eccessivo per il vostro problema, il Guava biblioteca ha qualche bella sintassi con Predicates e fa la valutazione di corto circuito o / e Predicates.

Essenzialmente, i confronti vengono trasformati in oggetti, confezionato in una collezione, e quindi iterate su. Per o predicati, il primo vero hit rendimenti dell'indice iterazione, e viceversa per e.

Se si tratta di leggibilità ho il concetto di separazione testato i dati dalla logica di test. Esempio di codice:

// declare data
DataType [] dataToTest = new DataType[] {
    defaultStock,
    defaultWholesale,
    defaultRetail,
    defaultDelivery
}

// define logic
boolean checkIfAnyNegative(DataType [] data) {
    boolean negativeValue = false;
    int i = 0;
    while (!negativeValue && i < data.length) {
        negativeValue = data[i++] < 0;
    }
    return negativeValue;
}

Il codice è più prolisso e di auto-esplicativo. Si può anche creare un array in chiamata di metodo, in questo modo:

checkIfAnyNegative(new DataType[] {
    defaultStock,
    defaultWholesale,
    defaultRetail,
    defaultDelivery
});

E 'più leggibile 'stringa di confronto', e ha anche vantaggi prestazionali corto circuito (a costo di allocazione matrice e metodo di chiamata).

Modifica Ancora più leggibilità può essere ottenuto semplicemente utilizzando i parametri varargs:

firma del metodo potrebbe essere:

boolean checkIfAnyNegative(DataType ... data)

E la chiamata potrebbe assomigliare a questo:

checkIfAnyNegative( defaultStock, defaultWholesale, defaultRetail, defaultDelivery );

E 'un vecchio post, ma al fine di fornire una prospettiva diversa per i principianti, vorrei fare un esempio.

Credo che il caso d'uso più comune per un operatore composto simile sarebbe +=. Sono sicuro che tutti noi scritto qualcosa di simile:

int a = 10;   // a = 10
a += 5;   // a = 15

Qual è stato il punto di questo? Il punto era evitare boilerplate ed eliminare il codice ripetitivo.

Quindi, la prossima linea fa esattamente lo stesso, evitando di digitare il b1 variabile due volte nella stessa riga.

b1 |= b2;
List<Integer> params = Arrays.asList (defaultStock, defaultWholesale, 
                                       defaultRetail, defaultDelivery);
int minParam = Collections.min (params);
negativeValue = minParam < 0;

|| booleano OR logico
| OR bit a bit

| = bit a bit OR inclusivo e assegnazione

Il motivo per cui | = non shortcircit è perché fa un OR bit a bit non un OR logico. Vale a dire:

C |= 2 is same as C = C | 2

Tutorial per gli operatori del Java

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