2015-03-11 10 views
28

Ho riscontrato un bug nel mio codebase, ho ristretto a ciò che ha causato questo comportamento. Il primo caso di test fallisce, mentre gli ultimi due hanno esito positivo.È un valore null immesso in Java

@Test 
public void testBooleanNull1() { 
    Boolean nullB = null; 
    assertFalse(Boolean.valueOf(nullB)); 
} 

@Test 
public void testBooleanNull2() { 
    String nullS = null; 
    assertFalse(Boolean.valueOf(nullS)); 
} 
@Test 
public void testBooleanNull3() { 
    assertFalse(Boolean.valueOf(null)); 
} 

so che Boolean.valueOf è un metodo di overload con due varianti si prende un String e l'altro prende una primitiva di tipo boolean.

ho il sospetto che questo sta accadendo a causa di auto-boxe, ma non sono sicuro se questo è il caso, inoltre, non so il motivo per cui null viene convertito a un Boolean per quanto ne so non è un null valido primitive tipo.

Sono passato a utilizzare BooleanUtils da Apache Commons, ho chiesto questo qui per capire meglio perché il comportamento è in questo modo.

+0

vedere anche http://stackoverflow.com/questions/2707322/what-is-null-in-java – cymatist

risposta

31

Questo

Boolean.valueOf(nullB) 

è un'invocazione di Boolean#valueOf(boolean).

Non riesce perché l'annullamento di casella del valore nullBBoolean non riesce con un NullPointerException. In altre parole, diventa

boolean val = nullB.booleanValue(); // at runtime nullB stores the value null 
Boolean.valueOf(val) 

Questo processo è descritto nel JLS here

Se r è un riferimento di tipo Boolean, quindi conversione unboxing converte r in r.booleanValue()

Questo

Boolean.valueOf(null) 

sta invocando overloaded version that accepts a String (poiché null non è un'espressione valida di tipo boolean).

Restituisce un Boolean con un valore rappresentato dalla stringa specificata. Il valore restituito booleano rappresenta un valore true se l'argomento stringa è non null ed è uguale, ignorando il caso, alla stringa "true".

1

Perché il secondo avrà esito positivo? Guarda il documento di public static Boolean valueOf(String s):

Restituisce un valore booleano con un valore rappresentato dalla stringa specificata. Il valore booleano restituito rappresenta un valore vero se l'argomento stringa è non è nullo ed è uguale, ignorando il caso, alla stringa "true".

È approvato una null in, quindi tornerà false.

5

risoluzione metodo overload è descritto in JLS:

15.12.2. In fase di compilazione Fase 2: Determinare firma del metodo

...

  1. La prima fase (§15.12.2.2) esegue la risoluzione di sovraccarico senza permettere la boxe o la conversione unboxing, o l'uso del metodo arità invocazione variabile. Se non viene trovato alcun metodo applicabile durante questa fase, l'elaborazione continua fino alla seconda fase.

Nel nostro caso, scegliendo tra Boolean.valueOf(boolean) e Boolean.valueOf(String) compilatore sceglie valueOf(String) perché non richiesto unboxing.

+0

Questa risposta colpisce l'unghia sulla testa! –

2

Dando uno sguardo al codice sorgente della classe Boolean

public static Boolean valueOf(String s) { 
    return toBoolean(s) ? TRUE : FALSE; 
} 

.. e poi:

private static boolean toBoolean(String name) { 
    return ((name != null) && name.equalsIgnoreCase("true")); 
} 

Se l'argomento String è null per Boolean.valueOf(String s), ritorna falso, quindi il secondo il caso ha successo.

Nel primo caso, l'uso di Boolean.valueOf che prende il tipo di dati come booleano, qui è ciò che la documentazione afferma:

public static Boolean valueOf(boolean b) 

Returns a Boolean instance representing the specified boolean value. If the specified boolean value is true, this method returns Boolean.TRUE; if it is false, this method returns Boolean.FALSE. If a new Boolean instance is not required, this method should generally be used in preference to the constructor Boolean(boolean), as this method is likely to yield significantly better space and time performance. 

Parameters: 
b - a boolean value. 
Returns: 
a Boolean instance representing b. 

Il parametro richiesto qui è un valore boolean che accetta True o False e non il valore Boolean che accetta True, False o null. Dato che hai superato il valore Boolean e non il valore boolean, suppongo che questo sia il motivo per cui non funziona.

Problemi correlati