Heim  >  Artikel  >  Java  >  Automatische Java-Boxing- und Unboxing-Quellcode-Analyse

Automatische Java-Boxing- und Unboxing-Quellcode-Analyse

WBOY
WBOYnach vorne
2023-05-09 12:10:111213Durchsuche

    Was ist Ein- und Auspacken?

    Der Prozess der Konvertierung des int-Basistyps in den Integer-Verpackungstyp wird als Boxen bezeichnet, und umgekehrt wird als Unboxing bezeichnet.

    Schauen Sie sich zunächst einen Teil des Codes an

    public static void main(String[] args) {
        Integer a = 127, b = 127;
        Integer c = 128, d= 128;
        System.out.println(a == b); // true
        System.out.println(c == d); // false
    }

    Ich weiß nicht, ob irgendjemand sonst nicht weiß, warum wahr und falsch in diesem Code vorkommen. Dies bringt uns zur Funktionsweise des Java-Boxens. Wir analysieren mit Fragen.

    Boxing (valueOf())

    public static Integer valueOf(int i) {
        // -128 - 127
        if (i >= IntegerCache.low && i <= IntegerCache.high)
            return IntegerCache.cache[i + (-IntegerCache.low)];
        return new Integer(i);
    }

    Wir können feststellen, dass es am Anfang eine Beurteilung gibt. Wenn der Wertebereich zwischen [-128.127] liegt, wird er aus diesem Cache (Integer-Array) entnommen, wenn nicht Sortiment ist dann direkt neu.

    Warum brauchen wir einen Cache von [-128.127]?

    Ich spreche von meinem Verständnis, denn in unserem Geschäft kann es verschiedene Status- und Identifikationsfelder vom Typ Integer geben. Diese Werte sind im Allgemeinen 0, 1, 2, 3 usw. und sie erscheinen häufiger. Wenn kein Cache vorhanden ist, werden häufig neue Objekte benötigt und dann freigegeben, was viel Speicherplatz verbraucht, sodass der Cache angezeigt wird, was uns erheblich dabei helfen kann, die Platzverschwendung zu optimieren.

    Warum ist es [-128.127]?

    Ich habe mir das hier nicht genauer erklärt. Es hängt hauptsächlich von grundlegenden Computerkenntnissen ab, nachdem Sie verstanden haben, was der Originalcode, der Umkehrcode und der Komplementcode sind. Es ist leicht zu erkennen, warum es in diesem Bereich liegt.

    Dieser Wert kann auch über Startparameter geändert werden.

    -XX:AutoBoxCacheMax=(size)

    Durch automatisches Boxen verursachte Leistungsprobleme

    Jetzt sollten Sie den Grund verstehen, warum der obige Code unterschiedliche Ergebnisse liefert. Haben Sie dann jemals darüber nachgedacht, wie zum Beispiel eines in unserem Unternehmen? Welche Probleme treten bei der for-Schleife auf? Schauen wir uns den folgenden Code an.

    public static void main(String[] args) {
        long startTime = System.currentTimeMillis();
        Integer count = 0;
        // int count = 0;
        for (int i = 0; i < 5000000; i++) {
            count += i;
        }
        System.out.println("计算时长:" + (System.currentTimeMillis() - startTime) + " ms");
    }
    
    // 执行结果:
    // Integer 计算时长:51 ms
    // int 计算时长:6 ms

    Anhand der Ausführungsergebnisse lässt sich dann deutlich erkennen, dass das automatische Boxen häufiger neuer Objekte und die Speicherzuweisung zu zeitlichen und räumlichen Leistungseinbußen führen.

    Kleine Zusammenfassung

    Durch die oben genannte Quellcode-Lesung und Testanalyse können wir den Schluss ziehen, dass wir, wenn wir normalerweise Statistiken berechnen oder Parameter in Methoden eingeben, unser Bestes geben sollten, um dieses Typkonvertierungsproblem zu vermeiden. Um die Ausführungseffizienz unseres gesamten Codes zu verbessern.

    Unboxing (intValue)

    Es gibt keine komplizierte Logik beim Unboxing und es gibt direkt den Grundtyp des Werts zurück.

    Zusätzlich: Erfolgt das automatische Ein- und Auspacken immer?

    Tatsächlich nicht unbedingt. Schauen Sie sich den Beispielcode unten an. Die Ausgabeergebnisse wurden nach der Ausgabeanweisung kommentiert.

    public static void main(String[] args) {
    // TODO 自动生成的方法存根
    Integer a = 1;
    Integer b = 2;
    Integer c = 3;
    Integer d = 3;
    Integer e = 321;
    Integer f = 321;
    Long g = 3L;
    System.out.println(c==d);//true
    //包装类的==在没有遇到算术运算的情况下不会自动拆箱
    System.out.println(e==f);//false
    System.out.println(c==(a+b));//true
    System.out.println(c.equals(a+b));//true
    System.out.println(g==(a+b));//true
    //equals方法不会处理数据转型关系
    System.out.println(g.equals(a+b));//false
    }

    Die Situationen, in denen automatisches Ein- und Auspacken auftritt, sind wie folgt:

    Autoboxing: Der Grundtyp wird dem Verpackungstyp zugewiesen. Zum Beispiel: Integer i1 = 1;

    Automatisches Unboxing:

    1. Der Verpackungstyp ist dem Basistyp zugeordnet. Zum Beispiel: int i2 = new Integer(1);

    2. Vergleichen Sie den Typ int mit dem Typ Integer. Wenn die Werte des Typs int und des Typs Integer gleich sind, ist das Ergebnis immer wahr.

    3. Integer-Typ trifft auf arithmetische Operationen

    Aber warum sind im obigen Beispiel die Ausgabeergebnisse von System.out.println(c==d); nicht dasselbe Gleiche?

    Hauptsächlich wegen der Methode Integer.valueOf(). Ein Teil des Quellcodes von Integer ist unten aufgeführt:

      //
       private static class IntegerCache {
            static final int low = -128;
            static final int high;
            static final Integer cache[];
    
            static {
                // high value may be configured by property
                int h = 127;
                String integerCacheHighPropValue =
                    sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
                if (integerCacheHighPropValue != null) {
                    try {
                        int i = parseInt(integerCacheHighPropValue);
                        i = Math.max(i, 127);
                        // Maximum array size is Integer.MAX_VALUE
                        h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
                    } catch( NumberFormatException nfe) {
                        // If the property cannot be parsed into an int, ignore it.
                    }
                }
                high = h;
    
                cache = new Integer[(high - low) + 1];
                int j = low;
                for(int k = 0; k < cache.length; k++)
                    cache[k] = new Integer(j++);
    
                // range [-128, 127] must be interned (JLS7 5.1.7)
                assert IntegerCache.high >= 127;
            }
                private IntegerCache() {}
        }
        
      public static Integer valueOf(int i) {
            if (i >= IntegerCache.low && i <= IntegerCache.high)
                return IntegerCache.cache[i + (-IntegerCache.low)];
            return new Integer(i);
        }

    IntegerCache ist die statische innere Klasse von Integer und valueOf() ist die Verpackungsmethode. Wie aus dem Quellcode hervorgeht, ist der Cache ein Cache-Array. Wenn der Eingabeparameter i der valueOf()-Methode im Bereich [-128,127] liegt, wird der Integer-Wert im Cache-Array zurückgegeben Es wird eine Ganzzahl erstellt.

    Aus diesem Grund sind die Ausgabeergebnisse von System.out.println(c==d); und System.out.println(e==f); c und d befinden sich im Cache-Intervall und geben daher dieselbe Referenz zurück. Während e und f nicht im Cache-Intervall liegen, geben sie eine neue Ganzzahl zurück, die nicht mehr dieselbe Referenz ist.

    Das obige ist der detaillierte Inhalt vonAutomatische Java-Boxing- und Unboxing-Quellcode-Analyse. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

    Stellungnahme:
    Dieser Artikel ist reproduziert unter:yisu.com. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen