Frage

die Verwendung von primitiven Datentypen und ihre jeweiligen Wrapper-Klassen Mischen, in Java, kann auf eine Reihe von Fehlern führen. Das folgende Beispiel verdeutlicht das Problem:

int i = 4;
...
if (i == 10)
  doStuff();

Später Sie herausfinden, dass Sie die Variable wollen i werden entweder definiert oder nicht definiert, so dass Sie die oben Instanziierung zu ändern:

Integer i = null;

Nun ist die Gleichheitsprüfung fehlschlägt.

Ist es gut Java Praxis immer die primitiven Wrapper-Klassen verwenden? Es würde sich offensichtlich einige Bugs aus dem Weg zu früh, aber was sind die Nachteile zu diesem? Hat es Auswirkungen auf die Leistung oder den Speicherbedarf der Anwendung? Gibt es hinterhältig gotchas?

War es hilfreich?

Lösung

Die eingerahmten Typen Mit hat haben sowohl Leistung und Speicherprobleme.

Wenn Vergleiche zu tun (zB (i == 10)), hat java den Typ unbox vor dem Vergleich zu tun. Auch i.equals(TEN) mit verwendet eine Methode aufrufen, die kostspieliger ist und (IMO) hässlicher als die == Syntax.

Re-Speicher, hat das Objekt auf dem Heap gespeichert werden (was auch einen Treffer auf Leistung in Anspruch nimmt) und Speichern des Wertes selbst.

Eine hinterhältige Gotcha? i.equals(j) wenn ich null ist.

Ich habe immer die Grundelemente verwenden, es sei denn, es können null werden, aber immer überprüfen null vor dem Vergleich in diesen Fällen.

Andere Tipps

Zum einen vom Schalten eines primitiven zur Verwendung eines Objekts unter Verwendung nur die Fähigkeit zu erhalten, es auf Null gesetzt ist wahrscheinlich eine schlechte Design-Entscheidung. Ich habe oft Argumente mit meinen Kollegen darüber, ob oder nicht null ist ein Sentinel-Wert, und meiner Meinung nach ist in der Regel, dass es nicht der Fall ist (und somit nicht wie Sentinel-Werte verboten sein sollte), aber in diesem speziellen Fall Sie gehen aus dem Weg, als ein Wächter-Wert zu verwenden. Bitte nicht. Erstellen Sie ein boolean, der angibt, ob Ihre ganze Zahl gültig ist, oder erstellen Sie einen neuen Typ, der die boolean und integer wickelt zusammen.

Normalerweise, wenn neuere Versionen von Java verwenden, finde ich, ich brauche nicht explizit zu erstellen oder wegen der Auto-Box Unterstützung für die Objektversionen von Primitiven gegossen, das einige Zeit in 1,5 (vielleicht 1,5 selbst) versetzt.

Ich würde vorschlagen, Primitiven die ganze Zeit mit, wenn Sie wirklich das Konzept der „Null“ haben.

Ja, die VM nicht Autoboxing und alles, was jetzt, aber es zu einigen wirklich wierd Fällen führen kann, in dem Sie eine Null-Zeiger-Ausnahme in einer Zeile Code bekommen, die Sie wirklich nicht erwarten, und Sie müssen anfangen tun null Kontrollen auf jeder mathematischen Operation. Sie können auch einige nicht-offensichtliche Verhalten anfangen, wenn Sie Arten und bekommen wierd Autoboxing Verhalten Mischen beginnen.

Für Schwimmer / verdoppelt Sie NaN als null behandeln kann, aber denken Sie daran, dass NaN! = NaN so noch Sie spezielle Prüfungen wie! Float.isNaN benötigen (x).

Es wäre wirklich schön, wenn es Sammlungen waren, die die primitiven Typen, anstelle von unterstützten die Zeit / Overhead-Box zu verschwenden.

In Ihrem Beispiel die if-Anweisung in Ordnung sein wird, bis Sie über 127 gehen (als Integer-Wert Autoboxing zwischengespeichert wird bis zu 127 und zurück die gleiche Instanz für jede Nummer auf diesen Wert nach oben)

So ist es schlimmer, als Sie es präsentieren ...

if( i == 10 )

wird nach wie vor funktionieren, aber

if( i == 128 )

fehl. Es ist aus Gründen wie diese, die ich immer explizit Objekte erstellen, wenn ich sie brauche, und neigen dazu, primitive Variablen zu bleiben, wenn möglich

Thee java POD-Typen sind aus einem bestimmten Grund gibt. Neben dem Aufwand können Sie den normalen Betrieb mit Objekten nicht. Eine ganze Zahl ist ein Objekt, das zugeordnet werden muß und Müll gesammelt. Ein int nicht.

Wenn dieser Wert leer sein, können Sie in Ihrem Design feststellen, dass Sie etwas brauchen sind anders.

Es gibt zwei Möglichkeiten - entweder der Wert nur Daten (der Code wird nicht anders handeln, wenn es in oder nicht gefüllt ist), oder es ist angibt, eigentlich, dass man zwei verschiedene Arten von Objekt haben hier (der Code verhält sich anders wenn es ein Wert als ein null)

eine, die nicht als First-Class-Mitglied überhaupt existiert -

Wenn es nur Daten für die Anzeige / Speicher ist, könnten Sie eine echte DTO betrachten verwenden. Diese werden im Allgemeinen einen Weg zu sehen, um zu überprüfen müssen, ob ein Wert gesetzt worden ist oder nicht.

Wenn Sie die null an einem gewissen Punkt überprüfen, Sie können unter Verwendung einer Unterklasse zu sein, weil, wenn es ein Unterschied ist, es in der Regel mehr sind. Wenigstens wollen Sie einen besseren Weg, um Ihre Differenz, um anzuzeigen, als „wenn primitiveIntValue == null“, die nicht wirklich etwas bedeutet.

Schalten Sie nicht auf nicht-Primitiven nur diese Möglichkeit zu erhalten. Verwenden Sie einen boolean, um anzuzeigen, ob der Wert gesetzt wurde oder nicht. Wenn Sie nicht, dass die Lösung gefällt und Sie wissen, dass Ihre ganze Zahlen in einer vernünftigen Grenze sein wird (oder kümmern sich nicht um die gelegentliche Fehler) verwenden, um einen bestimmten Wert ‚nicht initialisiert‘, wie Integer.MIN_VALUE anzuzeigen. Aber das ist eine viel weniger sichere Lösung als die boolean.

Wenn Sie zu, dass got ‚Später‘ Punkt, ein wenig mehr Arbeit benötigt während des Refactoring durchgeführt werden. Verwenden Sie Primitiven, wenn möglich. (Kapitalperiode) Dann POJOs machen, wenn mehr Funktionalität benötigt wird. Die Wrapper-Klasse, meiner Meinung nach, sind am besten für Daten verwendet, die über den Draht reisen muss, was bedeutet, vernetzte Anwendungen. Zulassen von NULL-Werte als akzeptable Werte verursacht Kopfschmerzen als ein System ‚wächst‘. Um viel Code verschwendet, oder verpasst, Bewachung, was einfache Vergleiche sein sollte.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top