Ho trovato un bug insolito nel mio codice recentemente attraverso test ad hoc casuali. Quindi, ho fatto un test per questo.Nell'operatore ternario di Java, il primo argomento può essere valutato anche se l'espressione ha dato come risultato un valore falso?
Ecco il mio banco di prova:
SampleRequest request = new SampleRequest();
request.setA(null);
request.setB(null);
assertEquals(null, request.getAOrB());
A e B sono definiti come tipi java.lang.Integer e hanno metodi setter diretti per impostare i loro valori nella richiesta.
Esiste anche un'enumerazione. Ha un valore intero primitivo e un metodo utilizzato in questo codice. Inserirò le parti pertinenti qui:
enum Swapper {
public int c;
Swapper findSwapperToUse(final int a) {
for(Swapper swapper : values()) {
if(swapper.c == a) {
return swapper;
}
}
return null;
}
}
Ora, ecco il metodo che è fonte di confusione. Se si richiama il metodo di test su quel metodo, si ottiene un NPE, ma sull'ultima riga del metodo.
public class SampleRequest {
private Integer A;
private Integer B;
public void setA(final Integer A) {
this.A = A;
}
public void setB(final Integer B) {
this.B = B;
}
public Integer getAOrB() {
return A != null ? Swapper.findSwapperToUse(A).c
: B;
}
}
Nel test, sia A che B sono impostati su null. Pertanto, A! = Null restituisce false. Tuttavia, ottengo una NullPointerException al numero di riga per la riga: B.
La mia ipotesi è che per qualche motivo la prima espressione, Swapper.findSwapperToUse (A) .c, sia in fase di valutazione, e pertanto A.intValue() viene richiamato tramite autoboxing, risultante in NullPointerException sul valore null. Attraverso il debug, è noto che findSwapperToUse() non è invocato.
Tuttavia, secondo questa questionthis non dovrebbe accadere: Java ternary (immediate if) evaluation
L'espressione operando non scelta non viene valutato per quel particolare valutazione dell'espressione condizionale.
Restituire un valore Null (B) non darà come risultato NullPointerException - è perfettamente corretto restituire qui un risultato nullo.
Che diavolo sta succedendo?
EDIT: Ho dimenticato di aggiungere che ho modificato il codice per evitare questo utilizzando un dritto fino if - il seguente codice funziona come previsto:
public Integer getAOrB() {
if(A != null) {
return Swapper.findSwapperToUse(A).c;
}
return B;
}
Il codice che hai dato non sarebbe la compilazione (ad esempio la mancanza di tipo di ritorno). Si prega di fornire un esempio breve ma * completo * e vedremo cosa sta succedendo. –
Come si può essere _ABSOLUTAMENTE__ certi che A sia nullo? –
Ho fornito il tipo di reso, mi dispiace - era Swapper. @Thor - a causa del test (request.setA (null), request.setB (null)) – MetroidFan2002