Prüfen ob Boolean Objekt null ist

Hallo,

ich habe folgende Aufgabenstellung bekommen.

Schreiben Sie eine Methode mit einem booleschen Parameter, abhängig vom Parameter soll die Methode “1”,“2”,“3” ausgeben.

Ich habe folgenden Code fertiggestellt

public class OneBooleanParameter
{    
    static public void getBooleanValue(Boolean b)
    {
        if(java.lang.Boolean.valueOf(b) == Boolean.TRUE) System.out.println("1");
        if(java.lang.Boolean.valueOf(b) == Boolean.FALSE) System.out.println("2");
        if(java.lang.Boolean.valueOf(b) == null) System.out.println("3");
    }
    
    public static void main(String[] args)
    {
        getBooleanValue( new Boolean(true) );
        getBooleanValue( new Boolean(false) );
        getBooleanValue( new Boolean(null) );
    }
}

Die Ausgabe:
1
2
2

Die Ausgabe zeigt das ein null Objekt nicht die Adresse null bekommt sondern false wird. Ist die Vermutung richtig und wenn nicht, wie prüfe ich ein Boolean Objekt ob es null ist.

Für Hilfe wäre ich dankbar.

Mfg
t2

Moin,

bin mir nicht sicher ob das eher so gemeint ist (ist auch ungetestet)

{
        getBooleanValue( true );
        getBooleanValue( false );
        getBooleanValue( null );
}

Nullable kann C# (4.0++) - aber nicht Java (oder ich habe was verpasst)


Ist null nicht automatisch false?

@mogel
Wenn ich keine Objekte erzeuge bekomme ich eine NullPointerException. Da beim primitiven boolean nur die Werte “true” und “false” gibt. Daher dachte ich ja das nur die Klasse Boolean gemeint sein kann, denn dort gibt es den Zustand “null”.
@groggy
Ich denke auch das “null” automatisch “false” ist, zumindest gibt die Ausgabe auf der Konsole beim dritten Aufruf nicht “3” sondern “2” aus.

Wäre es hier nicht angebracht den Parameter schlicht und einfach auf null zu prüfen? Getestet habe ich’s jetzt nicht (und es ist eine Weile her das ich zuletzt was in Java geschrieben habe), aber normalerweise würde man doch sowas schreiben wie:

    static public void getBooleanValue(Boolean b)
    {
        if(b == null) System.out.println("3");
        if(java.lang.Boolean.valueOf(b) == Boolean.TRUE) System.out.println("1");
        if(java.lang.Boolean.valueOf(b) == Boolean.FALSE) System.out.println("2");
    }

    public static void main(String[] args)
    {
        getBooleanValue( new Boolean(true) );
        getBooleanValue( new Boolean(false) );
        getBooleanValue( null );
    }

@TO
du hast hier glaube ich nicht ganz verstanden was NULL ist

in deinem code erzeugst du ja ein objekt dem du lediglich NULL übergibst, du hast aber trotzdem ein objekt

und dann prüfst du mit Boolean.valueOf(Object) … das kann NIE null sein …

  1. weil du ein objekt übergibst
  2. weil valueOf() selbst ein objekt erzeugt … welches du versuchst auf NULL zu prüfen

das du nach mogels variante eine NPE bekommst ist auch einfach erklärt da du einer methode NULL übergibst die damit nicht umgehen kann

und nebenbei : man testet grundsätzlich ERST ob der parameter NULL ist und DANN alles andere

Der Boolean-Wrapper und sein Kind:
Die Klasse Boolean ist ein Designfehler, weil man eh’ selbst bestimmen will, welche Objektkombis als WAHR erkannt werden sollen. Von daher schreibt man sich Boolean-Wrapper (unbewusst) ohnehin immer selbst. Was wäre z.B. wenn man boolsche Strings lokalisieren will? Dann ist man mit dem Wrapper schon mal schlecht bedient. Ferner gibt es ohnehin nur zwei Zustände, welche man als Konstanten festlegen kann. Öffentliche Konstruktoren sind also komplett überflüssig, erst recht dann, wenn sie fest verdrahtet bestimmen, welche Objekte (Strings) als TRUE definiert werden.
new Boolean(null);ist also nur deswegen FALSE, weil der String, welcher null ist, als false interpretiert wird.
Ausserdem:
if(Boolean.valueOf(b) == Boolean.TRUE) { // resp. Boolean.FALSEist das falscheste was man machen kann, ein sog. Pitfall, denn durch den new-Operator können sehr sehr viele Boolsche Objekte erzeugt werden, die evtl. alle inhaltlich gleich sein können, aber niemals identisch sein müssen. Entweder man schreibt

} else {
}```oder man vergleicht die Objekte mit "equals()". Bei letzterem (und der "if(b)"-Variante) bekommt man sogar (wenn man will) seine gewünschte NullpointerException, wenn ein Null-Objekt übergeben wurde.
Am besten ists, man streicht Boolean (also nur diese Wrapper-Klasse) aus seinem Gedächtnis.

was praktisch stimmt aufgrund der Implementierung, aber theoretisch nicht, da valueOf auch null zurueckgeben koennte, wenn der parameter null ist.

Ums nochmal zusammenzufassen: Boolean.valueOf gibt false zurueck, wenn der parameter null ist. Wie schon angemerkt ist die Frage wo und wie du null haben willst.

Also da muss ich mal einhaken…

Das:[quote=Spacerat]if(Boolean.valueOf(b)) { {[/quote]Funktioniert auch nur wegen dem Autoboxing. *.valueOf() liefert immer ein Objekt des Typs auf dem es Aufgerufen wird. In diesem Fall muss dieses Objekt dann noch in einen primitiven boolean auto-un-boxed werden.

Außerdem muss der Parameter b (der vom Typ Boolean ist) selbst in einen primitiven boolean auto-un-boxed werden, weil der Parameter von Boolean.valueOf(b) eben ein primitiver boolean ist, und kein Objekt. Die NPE sollte also auch hier geworfen werden.

bye
TT

Der Ansatz steckt voller Fehler:

  1. Warum überhaupt Boolean.valueOf, wenn Du doch schon einen gewrappten Boolean als Parameter hast?
  2. Auch bei Boolean gilt ,wie bei fast allen nicht primitiven Typen, dass mit equals zu vergleichen ist. Oder, wenn “==”, dann Autounboxing richtig und nullsafe verwenden.
  3. Auch wenn Du den null-Fall gleich am Anfang prüfen würdest, wäre die Gefahr der NPE nicht gebannt. Das würde entweder durch if-else oder returns im if-Block bzw. durch vorsichtige Implementierung vermieden.
    Mein Vorschlag für funktionierenden Code:
  // denn das ist das was die Methode in Wirklichkeit macht.
  public static void printNumberForBoolean(Boolean b) {
    // null-Prüfung gleich am Anfang
    if (b == null) {
                // ^ Auch bei nur einer Zeile im Block, unbedingt angewöhnen zu klammern!
      System.out.println("3");
    }
    // Wir nutzen else. Also wissen wir hier, b ist nicht null. Hier kann sicher auto-ungeboxed werden.
    // Damit kann b als primitives true/false direkt in der if-Bedingung
    // geprüft werden und man spart sich einen Aufruf von Boolean.TRUE.equals(b).
    else if (b) {
      System.out.println("1");
    } 
    // Hier kann b nur noch false sein. Die explizite Prüfung darauf ist
    // unnötig. Ein einfaches else reicht hier.
    else {
      System.out.println("2");
    }
  }

[QUOTE=Timothy_Truckle;81928]Also da muss ich mal einhaken…

Das:Funktioniert auch nur wegen dem Autoboxing. *.valueOf() liefert immer ein Objekt des Typs auf dem es Aufgerufen wird. In diesem Fall muss dieses Objekt dann noch in einen primitiven boolean auto-un-boxed werden.

Außerdem muss der Parameter b (der vom Typ Boolean ist) selbst in einen primitiven boolean auto-un-boxed werden, weil der Parameter von Boolean.valueOf(b) eben ein primitiver boolean ist, und kein Objekt. Die NPE sollte also auch hier geworfen werden.

bye
TT[/QUOTE]Was? :o Ja, stimmt gewaltig. :o Aber bei b = null wird die Methode aufgerufen, die einen String erwartet und diese liefert dann false. Ist aber eh’ Wurscht, der Boolean-Wrapper bleibt ‘ne “Fehlkonstruktion”. Hab’ das Gefühl, der existiert nur der Vollständigkeit halber.

Bestimmt würde da jemand sagen, der syntaktische Zucker liege darin, dass der Wert des Parameters Boolean b auch eine Nullreferenz sein kann könnte. lernen, lernen, lernen…

Nunja, sollte man mal booleans in einer Collection benötigen…

Generell unterstütze ich aber die Meinung dieses Artikels (also, Antipattern “Troolean”)

http://deadmeta4.com/2010/05/19/trooleans/

Also, wenn man String als Wrapper bezeichnen darf, dann ist es nur logisch folgerichtig/konsequent, dass es auch Wrapper für boolean, byte, char, short, int, long, float, double gibt. Und richtig erklärt, Collections beinhalten nur von Object abgeleitet Objekte oder Object. Was hier stört, ist dass new Boolean(null) nicht sofort eine Exception (NPE) auslöst, sondern einen valides Objekt (mit Wert…) repräsentiert. Vorher bin ich übrigens auch noch net auf diese Aufgabenstellung gestoßen.

[QUOTE=CyborgBeta]Also, wenn man String als Wrapper bezeichnen darf, dann ist es nur logisch folgerichtig/konsequent, dass es auch Wrapper für boolean, byte, char, short, int, long, float, double gibt. Und richtig erklärt, Collections beinhalten nur von Object abgeleitet Objekte oder Object. Was hier stört, ist dass new Boolean(null) nicht sofort eine Exception (NPE) auslöst, sondern einen valides Objekt (mit Wert…) repräsentiert. Vorher bin ich übrigens auch noch net auf diese Aufgabenstellung gestoßen.[/QUOTE]Nein, String ist kein Wrapper. Wrapper gibt es nur für Primitivtypen, als da wären boolean, byte, short, char (Character), int (Integer), long, float und double. String wird nur von all diesen Wrappern unterstützt, um Typwandlungen aus Texten zu erleichtern. Darum geht’s aber nicht, wenn man Boolean als “Unfall”, “Kropf” oder ähnliches bezeichnet. Boolean ist seit Java5 (also seitdem es AutoBoxing gibt) halt recht überflüssig.

Hallo,

entschuldigt bitte das Ich mich erst so spät wieder melde.
Ich bedanke mich für all eure Antworten, wenn sie auch erst mal dazu führten, dass ich gar nicht mehr durchgesehen habe.
Dennoch kann ich sagen, dass ich die Aufgabenstellung mittlerweile lösen konnte und ich wieder was dazu gelernt habe.

Ich habe jedoch noch eine Frage, und zwar habe ich immer von “AutoBoxing” und “Autounboxing” gelesen, auch mein Eclipse gibt mir bei Verwendung von “Double” oder “Integer”
immer ein “Warning” welches sich auf zuvor genannte Begrifflichkeiten bezieht.
Könnte mir jemand von Euch erklären was ich darunter zu verstehen habe?

Es gibt primitive Datentypen und Objecte. In bestimmten Szenarien ist es nötig, aus primitiven Datentypen Objekte zu machen. Das hat aber mehr mit der internen Verwaltung seitens Java zu tun als mit der Logik die man selbst implementiert. Häufigstes Beispiel ist eine Collection (List, Set, etc) in der man simple Zahlen speichern will. Hier können aber nur Objekte gespeichert werden, daher wird automatisch um ein “int” ein “Integer”-Objekt gebaut. Das ist so trivial, dass man sich darum nicht selber kümmern muss.

Statt

private List<Integer> ints;
    
    private void sinnlos(){
        int a = 1;
        Integer b = new Integer(a);
        ints.add(b);
        b = ints.get(0);
        a = b.intValue();
    }```

reicht 

private List ints;

private void sinnvoll(){
    int a = 1;
    ints.add(a);
    a = ints.get(0);
   
}

Die Konvertierung von einem “kleineren” primitiven Datentyp in einen “größeren” nennt man übrigens net Auto(un)b/Boxing, sondern…

[QUOTE=CyborgBeta]Die Konvertierung von einem “kleineren” primitiven Datentyp in einen “größeren” nennt man übrigens net Auto(un)b/Boxing, sondern…[/QUOTE]Das ist falsch. Als AutoBoxing bezeichnet man die automatische Überführung von Primitiven in ein Wrapperobjekt und umgekehrt. Das was du meinst ist schlicht eine automatische Konvertierung (Autocast), welche bei Primitiven durch N-Flag-Expansion erreicht wird.

Edit: :o irgendwie hab ich ein “net” (nicht) überlesen…

sondern?