2013-08-05 9 views
5

Wenn ich für ein Objekt nach einem Tier frage und das zurückgegebene Objekt nicht null ist, aber Nullvariablen enthält, ist das falsch? Zum Beispiel kann ich animal.getDeathDate() anrufen; und da es noch nicht tot ist, gibt es null zurück. Für eine Turtle würde null zurückgeben, da sie nicht fliegen kann, bis das Turtle-Raketenpaket hinzugefügt wurde. Usw.Ist ein Java-Objekt, das Nullvariablen enthält, ein Anti-Pattern? Wenn ja, welcher?

Ich dachte, dass dies eine schlechte Möglichkeit war, Dinge zu tun, da es oft eine Vielzahl von Nullprüfungen erforderlich macht, während die Methoden des Objekts aufgerufen werden, um zu überprüfen, dass sie Nicht-Null-Werte enthalten. Gibt es Links zu Informationen darüber, die mich und meine Mitarbeiter weiter informieren könnten?

+1

Möglicherweise möchten Sie das Null-Objekt-Muster. – SLaks

+0

Ich las über das Null-Objekt-Muster, aber ich war nicht sicher, ob es Objekte adressierte, die Nullvariablen hatten. Ich dachte, es hängt mehr damit zusammen, ob ein NULL-Objekt oder ein Objekt von einer Abfrage-Methode zurückgegeben werden sollte und nicht von einem Daten-Objekt. – FooBar

+1

Das Null-Objekt-Muster gilt grundsätzlich für jedes "null". Das Gewährleisten von Nicht-Null-Werten macht den Code viel einfacher. – zapl

Antwort

4

null ist oft nicht eindeutig. War das Feld noch nicht initialisiert oder hat es keinen Wert?

Es ist oft besser für nicht initialisierte/irrelevante Felder einige vordefinierte Konstante zu haben.

Noch besser ist es, eine Klasse nur eine Verantwortung zu haben. Methoden wie sollte nicht vererbt werden, sondern kommen aus der Implementierung einer Schnittstelle (Methoden wie getDeathDate(), sollte jedoch eine vordefinierte Konstante zurückgegeben, wenn Animal noch am Leben ist).

As brought by google-guava docs:

Doug Lea (Autor von java.util.concurrent Paket), dass Null s**ks.

Auch sir C. A. R. Hoare, Erfinder der null Referenz sagte: I call it my billion-dollar mistake.

Das ist eine breite Schulter zu legen.

+0

Das ist meiner Meinung, ich hatte auf etwas Referenzmaterial gehofft um es zu unterstützen. War nicht in der Lage, mehr als eine ziemlich große Debatte um das Null-Objekt-Muster durch Google zu drehen. – FooBar

+0

@ FooBar hinzugefügt eine Referenz. – yair

+0

Was schlagen Sie vor, um 'getDeathDate()' zurückzugeben? – Gabe

1

Null kann manchmal eine durchaus vernünftige Art und Weise sein, die darstellen, dass ein Objekt eine bestimmte Eigenschaft fehlt.

Es ist jedoch nützlich, eine einzige Prüfung zu ermöglichen.

Für ein Array oder eine Liste, ist es oft besser, eine Variable zu haben, die immer ungleich Null ist, sondern auf eine leere Liste verweisen. Andernfalls muss überprüft werden, dass die Variable nicht null ist und dass die Liste Mitglieder hat.

0

Dies ist nur meine Meinung, aber Ihr Beispiel klingt wie ein Anti-Muster (als ein entartetes Null-Objekt), da Sie Null-Prüfungen durchführen müssen, was die Methoden auf dem "Null-Objekt" zurückgeben. Wenn Sie diese Getter überhaupt nicht aufrufen, wäre Ihr Beispiel korrekt.

Die Idee mit Null-Objekten ist, dass Sie überhaupt keine Null-Prüfungen durchführen müssen, also könnte es funktionieren, wenn Ihre Getter andere Null-Objekte zurückgeben, oder die Methoden tell-don't-ask Ansatz verwenden (und einfach zurückgeben).

4

Rückkehr null für den Tod Datum für ein lebendiges Tier ist durchaus sinnvoll, aber in Fällen wie diesen ich es besser finde eine boolean Tod Prüfung bieten:

public boolean isDead() { 
    return deathDate != null; 
} 

Dies bietet eine vernünftige Art und Weise den Todes des Prüfens -ness einer Instanz ohne plump nULL-Prüfung des Attributs:

// this is ugly and exposes the choice of the value of the field when alive 
if (animal.getDeathDate() != null) { 
    // the animal is dead 
} 

Mit dem isDead() Verfahren vorhanden, würden Sie in Ihren Rechten, dies zu tun:

public Date getDeathDate() { 
    if (deathDate == null) 
     throw new IllegalStateException("Death has not occurred"); 
    return deathDate; 
} 

die Fluggeschwindigkeit Schildkröte In Bezug auf, könnten Sie den gleichen Ansatz anwenden, obwohl ich behaupten würde, dass es ein Problem in der Klasse Design - nicht alle Tiere fliegen, so dass die Animal Klasse soll nicht ein getFlyingSpeed() Methode.

Verwenden Sie stattdessen etwas wie folgt aus:

interface Flyer { 
    Integer getFlightSpeed(); 
} 

class Animal {} 

class Turtle extends Animal {} 

class Eagle extends Animal implements Flyer { 
    public Integer getFlightSpeed() { 
     // 
    } 
} 
+0

für den Fall GetFlyingSpeed, anstatt eine Schnittstelle zu implementieren, können wir eine Instanzvariable in Tierklasse haben, beziehen sich auf Flyer-Typ (wird zwei Methoden in dieser Schnittstelle haben wie fliegen und die Fluggeschwindigkeit bekommen)? – Atul

+0

Eine canFly() ist nicht notwendig oder wünschenswert, weil a) Sie 'if (animal instaceof Flyer)' verwenden können, und b) Sie sowieso auf Flyer umwandeln müssen, um auf die Flyer-Methoden zugreifen zu können, damit Sie bereits wissen, dass es sich um einen Flyer handelt weil Sie eine Instanz der Überprüfung durchführen müssen, bevor Sie casten können. – Bohemian

0

Null völlig in Ordnung sind, aber Sie sollten versuchen, sie zu vermeiden Standardwerten so viel wie möglich

Zum Beispiel leere Liste sollte stattdessen zurückgegeben werden von null enum-Datentypen sollte UNKNOWN

Vor Annahme enthält macht das Leben von API Verbraucher leicht

In Ihrem Beispiel würde ich null von animal.getDeathDate zurückgeben, da ich an keinen geeigneten Standardwert denken kann.

I bequeme Methode liefert animal.isDead wahr/falsch

Für getFlightSpeed ​​Rückkehr() Ich würde 0 zurück für Ihren Fall

0

Null-Objekt-Muster in der Tat kann bei null Variablen verwendet werden. Im Falle von Turtle.getFlightSpeed ​​() können Sie SPEED-Konzept abstrahieren (kann Interface oder abstrakte Klasse sein) und ein NULL-Objekt implementieren, das "unable to fly" -Szenario implementiert. Dies wird helfen, Turtle-Klassen Standardverhalten zuzuweisen. Rückgabe von null im Falle von animal.getDeathDate() scheint in Ordnung

1

Ich glaube nicht, dass es falsch ist. Als Analogie, denken Sie an die Semantik von NULL in SQL:

Eine gute Möglichkeit, sich daran zu erinnern, was NULL bedeutet, dass in Bezug auf die Informationen zu erinnern ist, „Fehlen eines Wertes“ ist nicht dasselbe wie „einen Wert von zero "; Ähnlich ist "das Fehlen einer Antwort" nicht dasselbe wie "eine Antwort von nein".

Es ist absolut gültig, die gleiche Logik in Java anzuwenden.

Um primitive Typen nullbar zu machen, überprüfen Sie die nullable types in C#. Es sollte einfach sein, Nullable als generisches Java zu implementieren.

0

Ich denke, dass für Tier.getDeathDate(), das null zurückgibt, wenn das Tier lebt, ist der richtige Weg, Dinge zu tun. Sie werden immer einen speziellen Code benötigen, um die 2 Fälle zu behandeln: lebendiges Tier und totes Tier, und es gibt kein nützliches Datum, an dem Sie zurückkehren können, wenn das Tier lebt.

Für getFlightSpeed ​​() könnten die Dinge anders sein. Ich weiß nicht genau, was es zurückgibt, aber lassen Sie uns nur für ein Beispiel vorstellen, es nur die Geschwindigkeit zurückgeben als m/s

In diesem Fall wird die Rückgabe 0 (oder ein Objekt mit dem gleichen Effekt) wird vollkommen Sinn machen, weil es beschreibt die Fluggeschwindigkeit.

+0

"Ich denke, dass für animal.getDeathDate() Null zurückgeben, wenn das Tier lebt, ist der richtige Weg, Dinge zu tun." Nun, was ist, wenn das Tier gestorben ist, aber niemand weiß wann? –

1

Eine wichtige NULL-Prüfregel, die ich habe, ist nie Null anstelle einer Liste oder eines Arrays zu platzieren.

Leere Listen und Arrays sind viel besser auszudrücken, was sie wirklich sind.