Maison  >  Article  >  Java  >  Analyse automatique du code source de boxe et de déballage Java

Analyse automatique du code source de boxe et de déballage Java

WBOY
WBOYavant
2023-05-09 12:10:111214parcourir

    Qu'est-ce que l'emballage et le déballage ?

    Le processus de conversion du type de base int en type d'emballage Integer est appelé boxing, et vice versa est appelé unboxing.

    Premier coup d'œil à un morceau de code

    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
    }

    Je ne sais pas si quelqu'un d'autre ne sait pas pourquoi vrai et faux apparaissent dans ce code. À partir de là, nous introduisons le fonctionnement de la boxe Java. Nous analysons avec des questions.

    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);
    }

    Nous pouvons constater qu'il y a un jugement au début. Si la plage de valeurs est comprise entre [-128,127], alors elle sera extraite de ce cache (tableau d'entiers), sinon This. la gamme est alors directement nouvelle.

    Pourquoi avons-nous besoin d'un cache de [-128,127] ?

    Je comprends de quoi je parle, car dans notre métier, il peut y avoir différents champs de type entier tels que le statut et l'identification. Ces valeurs​​sont généralement 0, 1, 2, 3 et autres, et elles. apparaissent plus fréquemment. S'il n'y a pas de cache, de nouveaux objets fréquents sont nécessaires puis libérés, ce qui consomme beaucoup d'espace mémoire, donc le cache apparaît, ce qui peut grandement nous aider à optimiser une certaine perte d'espace.

    Pourquoi est-ce [-128,127] ?

    J'ai jeté un œil à cela. Je n'expliquerai pas la raison spécifique ici. Cela repose principalement sur des connaissances informatiques de base. Après avoir compris ce que sont le code d'origine, le code inverse et le code complémentaire. Il est facile de savoir pourquoi il se situe dans cette fourchette.

    Cette valeur peut également être modifiée via les paramètres de démarrage.

    -XX:AutoBoxCacheMax=(size)

    Problèmes de performances causés par la boxe automatique

    Alors maintenant, vous devriez comprendre la raison pour laquelle le code ci-dessus a des résultats différents, alors y avez-vous déjà pensé, comme celui de notre entreprise Dans la boucle for, des opérations de données statistiques comme celle-ci se produisent s'il y a une boxe automatique, quels problèmes surviendront ? Regardons le morceau de code suivant.

    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

    Ensuite, à travers les résultats d'exécution, on peut clairement découvrir que le boxing automatique de nouveaux objets fréquents et l'allocation de mémoire entraînent des pertes de performances dans le temps et dans l'espace.

    Petit résumé

    Grâce à la lecture du code source et à l'analyse des tests ci-dessus, nous pouvons conclure que lorsque nous calculons habituellement des statistiques ou saisissons des paramètres dans les méthodes, nous devrions faire de notre mieux pour éviter ce problème de conversion de type. Pour améliorer l’efficacité d’exécution de l’ensemble de notre code.

    Unboxing (intValue)

    Il n'y a pas de logique compliquée dans le unboxing et il renvoie directement le type de base de la valeur.

    Supplément : la mise en boîte et le déballage automatiques se produisent-ils toujours ?

    En fait, pas nécessairement. Regardez l'exemple de code ci-dessous. Les résultats de sortie ont été commentés après l'instruction de sortie.

    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
    }

    Les situations dans lesquelles le boxing et le unboxing automatiques se produisent sont les suivantes :

    Autoboxing : Le type de base est attribué au type d'emballage. Par exemple : Entier i1 = 1;

    Déballage automatique :

    1. Le type d'emballage est attribué au type de base. Par exemple : int i2 = new Integer(1);

    2. Comparez le type int avec le type Integer. Si les valeurs du type int et du type Integer sont égales, le résultat est toujours vrai.

    3. Le type entier rencontre des opérations arithmétiques

    Mais pourquoi dans l'exemple ci-dessus, les résultats de sortie de System.out.println(c==d); pas pareil Pareil ?

    Principalement à cause de la méthode Integer.valueOf(). Une partie du code source d'Integer est publiée ci-dessous :

      //
       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 est la classe interne statique d'Integer et valueOf() est la méthode d'empaquetage. Comme le montre le code source, le cache est un tableau de cache. Lorsque le paramètre d'entrée i de la méthode valueOf() est compris dans la plage [-128,127], la valeur entière du tableau de cache sera renvoyée. Un entier sera créé.

    C'est pourquoi les résultats de sortie de System.out.println(c==d); et System.out.println(e==f); c et d sont dans l'intervalle de cache, ils renvoient donc la même référence ; tandis que e et f ne sont pas dans l'intervalle de cache, ils renvoient un nouvel Integer, qui n'est plus la même référence.

    Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

    Déclaration:
    Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer