2015-03-11 19 views
28
eingegeben

Ich habe einen Fehler in meiner Codebasis festgestellt, ich habe darauf beschränkt, was dieses Verhalten verursacht. Der erste Testfall schlägt fehl, während die letzten beiden erfolgreich sind.Ist null 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)); 
} 

Ich weiß, dass Boolean.valueOf eine überladene Methode mit zwei Varianten ist man ein String nimmt und der andere nimmt eine primitive vom Typ boolean.

Ich vermute, dass dies wegen der Auto-Box geschieht, aber ich bin mir nicht sicher, ob das der Fall ist, außerdem weiß ich nicht, warum null wird bis zu einem Boolean umgewandelt werden, wie ich weiß null ist keine Gültig primitive Typ.

Ich habe weiter mit der Verwendung BooleanUtils von Apache Commons, ich fragte dies hier, um besser zu verstehen, warum das Verhalten auf diese Weise ist.

+0

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

Antwort

31

Diese

Boolean.valueOf(nullB) 

ist ein Aufruf von Boolean#valueOf(boolean).

Es schlägt fehl, weil das Unboxing des Werts nullB mit einem NullPointerException fehlschlägt. Mit anderen Worten wird es

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

Dieser Prozess in der JLS beschrieben here

Wenn r eine Referenz vom Typ Boolean, dann unboxing Umwandlung wandelt r in r.booleanValue()

Diese

Boolean.valueOf(null) 

ruft die overloaded version that accepts a String (seit null ist kein gültiger Ausdruck des Typs boolean).

Gibt eine 10 mit einem Wert zurück, der durch die angegebene Zeichenfolge dargestellt wird. Der zurückgegebene Boolean-Wert stellt einen true-Wert dar, wenn das Zeichenfolgenargument nicht null ist und unter Beachtung der Groß-/Kleinschreibung der Zeichenfolge "true" entspricht.

1

Warum der zweite erfolgreich sein wird? Betrachten Sie das Dokument public static Boolean valueOf(String s):

Gibt einen booleschen Wert mit einem Wert zurück, der durch die angegebene Zeichenfolge dargestellt wird. Der zurückgegebene Boolesche Wert stellt einen wahren Wert dar, wenn das Zeichenfolgenargument nicht null ist und unter Beachtung der Groß-/Kleinschreibung der Zeichenfolge "true" entspricht.

Sie übergeben ein null in, so wird es false zurück.

5

überladene Methode Auflösung wird in JLS beschrieben:

15.12.2. Compiler-Schritt 2: Bestimme Methodensignatur

...

  1. der ersten Phase (§15.12.2.2) führt, ohne Überladungsauflösung Boxen oder unboxing Umwandlung ermöglicht wird, oder die Verwendung von variablen arity Methodenaufruf. Wenn während dieser Phase keine geeignete Methode gefunden wird, wird die Verarbeitung in der zweiten Phase fortgesetzt.

In unserem Fall zwischen Boolean.valueOf(boolean) und Boolean.valueOf(String) Compiler Wahl wählt valueOf(String), weil es nicht Unboxing erforderlich ist.

+0

Diese Antwort trifft den Nagel auf den Kopf! –

2

einen Blick auf den Quellcode bilde Boolean

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

.. und dann:

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

Wenn das String-Argument null für Boolean.valueOf(String s) ist, wird es false zurück, damit die zweite Fall gelingt.

Im ersten Fall auf die Verwendung von Boolean.valueOf, die den Datentyp als boolean nimmt, hier ist das, was die Dokumentation heißt es:

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. 

Der Parameter hier braucht, ist ein Wert, der booleanTrue annimmt oder False und nicht Boolean Wert, der True, False oder null akzeptiert. Da Sie einen Wert und nicht boolean Wert übergeben, denke ich, dass es der Grund ist, warum es scheitert.