[JAVA] Punkt 61: Bevorzugen Sie primitive Typen gegenüber primitiven Boxen

61. Das Grundelement sollte aus dem Grundelement in der Box ausgewählt werden

Unterschied zwischen primitivem Typ und primitivem Typ

Wie in Punkt 6 erwähnt, ist der Unterschied zwischen dem primitiven Typ (im Folgenden "primitiv") und dem primitiven Typ (im Folgenden "primitiv") aufgrund des automatischen Boxens und des automatischen Entpackens nicht eindeutig. Es gibt jedoch Unterschiede zwischen den beiden, und Sie müssen sich der Unterschiede bewusst sein, wenn Sie sie verwenden. Es gibt drei Unterschiede

Beispiel für einen Fehler bei der Verwendung eines Boxed-Primitivs

Das Grundelement hat nur einen Wert, aber das umrahmte Grundelement hat eine vom Wert abweichende Referenz

Auf den ersten Blick sieht der folgende Code wie eine Methode aus, die einen guten Vergleich ermöglicht.

// Broken comparator - can you spot the flaw?
Comparator<Integer> naturalOrder =
    (i, j) -> (i < j) ? -1 : (i == j ? 0 : 1);

Wenn Sie diese Methode jedoch wie `` naturalOrder.compare (neue Ganzzahl (42), neue Ganzzahl (42)) `verwenden, sollte sie 0 zurückgeben, da sie gleich sein soll, aber tatsächlich 1 zurückgibt. .. Das erste Urteil (i <j) wird automatisch entpackt und funktioniert korrekt. Andererseits betrachtet das zweite Urteil (i == j) den gleichen Wert, dh ob die Referenzen gleich sind. Daher ist dieser Vergleich nicht wahr und 1 wird als Ergebnis zurückgegeben. Es ist normalerweise falsch, den Operator == für Grundelemente mit Kästchen zu verwenden.

Um den obigen Fehler zu vermeiden, verwenden Sie `Comparator.naturalOrder ()` oder führen Sie einen primitiven Vergleich wie folgt durch, wenn Sie einen eigenen Vergleicher schreiben.

Comparator<Integer> naturalOrder = (iBoxed, jBoxed) -> {
    int i = iBoxed, j = jBoxed; // Auto-unboxing
    return i < j ? -1 : (i == j ? 0 : 1);
};

Ein Grundelement kann nur einen funktionalen Wert haben, ein umrahmtes Grundelement kann jedoch eine Null haben (nicht funktionierender Wert).

Im folgenden Programm tritt nullpo auf.

package tryAny.effectiveJava;

public class BoxedPrimitive {
    static Integer i;

    public static void main(String[] args) {
        if (i == 42)
            System.out.println("Unbelievable");
    }

}

Bei i == 47 werden Integer und int verglichen. In einem Prozess, in dem Boxed Primitive und Primitive gemischt werden, ** wird Boxed Primitive in den meisten Fällen automatisch entpackt. ** ** ** Das Entpacken eines Objekts, das auf null verweist, führt zu nullpo, was hier geschieht.

primitiv ist besser in Bezug auf Zeit und Speicherplatz

Das folgende Programm wird in Punkt 6 behandelt.

package tryAny.effectiveJava;

public class BoxedPrimitive2 {
    // Hideously slow program! Can you spot the object creation?
    public static void main(String[] args) {
        Long sum = 0L;
        for (long i = 0; i < Integer.MAX_VALUE; i++) {
            sum += i;
        }
        System.out.println(sum);
    }

}

Dies ist viel langsamer als wenn der lokale Variablentyp auf long eingestellt ist, da das Ein- und Auspacken wiederholt erfolgt.

Zusammenfassung

Es gab drei Probleme, die ersten beiden hatten schlechte Ergebnisse und das letzte hatte eine schlechte Leistung.

Bei Verwendung des umrahmten Grundelements gibt es die folgenden Fälle.

Recommended Posts

Punkt 61: Bevorzugen Sie primitive Typen gegenüber primitiven Boxen
Punkt 89: Für die Steuerung bevorzugen Sie Aufzählungstypen gegenüber readResolve
Punkt 28: Listen Arrays vorziehen
Punkt 65: Schnittstellen der Reflexion vorziehen
Punkt 43: Bevorzugen Sie Methodenverweise auf Lambdas
Punkt 39: Bevorzugen Sie Anmerkungen gegenüber Namensmustern
Punkt 85: Bevorzugen Sie Alternativen zur Java-Serialisierung
Punkt 41: Verwenden Sie Markierungsschnittstellen, um Typen zu definieren
Punkt 58: Bevorzugen Sie für jede Schleife herkömmliche Schleifen
Punkt 23: Bevorzugen Sie Klassenhierarchien gegenüber markierten Klassen
Punkt 81: Bevorzugen Sie Parallelitätsdienstprogramme, um zu warten und zu benachrichtigen
Punkt 80: Ziehen Sie Executoren, Aufgaben und Streams Threads vor
Punkt 47: Sammlung als Rückgabetyp dem Stream vorziehen
Punkt 29: Generische Typen bevorzugen