JavaRush /Blog Java /Random-FR /Autoboxing et unboxing en Java
Viacheslav
Niveau 3

Autoboxing et unboxing en Java

Publié dans le groupe Random-FR
<h2>Introduction</h2>Un langage de programmation, comme la langue que les gens parlent, vit et change, de nouveaux phénomènes y apparaissent pour rendre le langage plus pratique à utiliser. Et comme nous le savons, le langage doit exprimer nos pensées de manière pratique.
Autoboxing et unboxing en Java - 1
Ainsi, dans Java SE 5, le mécanisme de boxing/unboxing a été introduit. Et un tutoriel distinct d'Oracle est consacré aux fonctionnalités de ce moyen d'exprimer des pensées : Autoboxing et Unboxing . <h2>Boxing à emballage automatique</h2>Regardons un exemple de Boxing à emballage automatique. Voyons d’abord comment cela fonctionne. Utilisons le site compilejava.net et créons une classe :
public class App {
    public static void main(String[] args) {
        Integer portNumber = 8080;
        if (args.length != 0) {
            portNumber = Integer.valueOf(args[0]);
        }
        System.out.println("Port number is: " + portNumber);
    }
}
Code simple. Nous pouvons spécifier le paramètre d'entrée et modifier la valeur du port. Comme on le voit, parce que nous lisons la valeur du port à partir Stringdes paramètres, nous Integerl'obtenons en la faisant passer Integer.valueOf. Par conséquent, nous sommes obligés de le spécifier non pas comme un type primitif, mais comme un type d'objet Integer. Et ici, nous obtenons d'une part, nous avons une variable objet, et la valeur par défaut est une primitive. Et il fonctionne. Mais nous ne croyons pas à la magie, n'est-ce pas ? Jetons un coup d'œil « sous le capot », comme on dit. Téléchargez le code source depuis compilejava.net en cliquant sur « Télécharger ZIP ». Après cela, extrayez l'archive téléchargée dans un répertoire et accédez-y. Faisons maintenant : javap -c -p App.classoù App.class est le fichier de classe compilé pour votre classe. Nous verrons du contenu comme celui-ci :
Autoboxing et unboxing en Java - 2
Il s’agit du même « bytecode » notoire. Mais ce qui est important pour nous maintenant, c'est ce que nous voyons. Tout d'abord, la primitive 8080 est placée sur la pile d'exécution de méthode, puis Integer.valueOf est exécuté . C'est la « magie » de la boxe. Et à l’intérieur, la magie ressemble à ceci :
Autoboxing et unboxing en Java - 3
Autrement dit, un nouveau sera pris Integerou sera obtenu Integerà partir du cache (le cache n'est rien de plus qu'un simple tableau d'entiers) en fonction de la valeur du nombre. Naturellement, Integeril n’y en a pas un seul qui a eu cette chance. Il existe toute une liste de types primitifs associés et de leurs wrappers (classes qui représentent les primitives dans le monde POO). Cette liste est donnée tout en bas du Tutoriel d'Oracle : « Autoboxing and Unboxing ». Il convient de noter tout de suite que les tableaux créés à partir de primitives n'ont pas de « wrapper » sans connecter de bibliothèques tierces. Ceux. Arrays.asListne fera pas int[]pour nous Listde Integer's. <h2>Unboxing</h2>Le processus inverse du boxing est appelé unboxing unboxing. Regardons un exemple de déballage :
public class App {

    public static void main(String[] args) {
        if (args.length == 0) {
            System.out.println("Please, enter params");
            return;
        }
      	int value = Math.abs(Integer.valueOf(args[0]));
        System.out.println("Absolute value is: " + value);
    }

}
Math.absn'accepte que les primitives. Ce qu'il faut faire? La classe wrapper a une méthode spéciale pour ce cas qui renvoie une primitive. Par exemple, c'est la Integerméthode intValue . Si nous regardons le bytecode, cela ressemble à ceci :
Autoboxing et unboxing en Java - 4
Comme vous pouvez le constater, pas de magie. Tout est en Java. Cela fonctionne « tout seul ». Pour notre commodité. <h2>Râteau</h2>
Autoboxing et unboxing en Java - 5
Tout outil, s’il est mal utilisé, devient une arme redoutable contre lui-même. Et le mécanisme automatique de boxing/unboxing en Java ne fait pas exception. La première comparaison évidente passe par ==. Je pense que c'est clair, mais regardons-y à nouveau :
public static void main(String[] args) {
    Integer inCacheValue = 127;
    Integer inCacheValue2 = 127;
    Integer notInCache = 128; // new Integer(129)
    Integer notInCache2 = 128; // new Integer(129)
    System.out.println(inCacheValue == inCacheValue2); //true
    System.out.println(notInCache == notInCache2); //false
}
Dans le premier cas, la valeur est extraite du Integercache de valeurs (voir explication de Boxing ci-dessus), et dans le second cas un nouvel objet sera créé à chaque fois. Mais ici, cela vaut la peine de réserver. Ce comportement dépend de la limite haute du cache ( java.lang.Integer.IntegerCache.high ). De plus, cette limite peut changer en raison d'autres paramètres. Vous pouvez lire la discussion sur ce sujet sur stackoverflow : Quelle est la taille du cache Integer ? Naturellement, les objets doivent être comparés en utilisant des valeurs égales : System.out.println(notInCache.equals(notInCache2)); le deuxième problème associé au même mécanisme est la performance. Toute boxe en Java équivaut à créer un nouvel objet. Si le numéro n'est pas inclus dans les valeurs du cache (c'est-à-dire -128 à 127), alors un nouvel objet sera créé à chaque fois. Si soudainement l'emballage (c'est-à-dire la mise en boîte) est effectué en boucle, cela entraînera une augmentation considérable du nombre d'objets inutiles et de la consommation de ressources pour le travail du ramasse-miettes. Ne soyez donc pas trop imprudent. Un troisième râteau, non moins douloureux, relève du même mécanisme :
public static void check(Integer value) {
    if (value <= 0) {
        throw new IllegalStateException("Value is too small");
    }
}
Dans ce code, la personne essayait clairement de ne pas contourner l’erreur. Mais il n'y a pas de chèque pour null. S'il s'agit de l'entrée null, alors au lieu d'une erreur compréhensible, nous obtiendrons une erreur incompréhensible NullPointerException. Parce qu'à titre de comparaison, Java va essayer de s'exécuter value.intValueet de planter, parce que... valuevolonté null. <h2>Conclusion</h2>Le mécanisme de boxing/unboxing permet au programmeur d'écrire moins de code et parfois de ne même pas penser à la conversion des primitives en objets et inversement. Mais cela ne veut pas dire que vous devez oublier son fonctionnement. Sinon, vous risquez de commettre une erreur qui n’apparaîtra peut-être pas immédiatement. Nous ne devons pas nous appuyer sur des parties du système qui ne sont pas entièrement sous notre contrôle (comme la frontière entière). Mais n'oubliez pas tous les avantages des classes wrapper (comme Integer). Souvent, ces classes wrapper disposent d'un ensemble de méthodes statiques supplémentaires qui rendront votre vie meilleure et votre code plus expressif. Voici un exemple de rattrapage :
public static void main(String[] args) {
    int first = 1;
    int second = 5;
    System.out.println(Integer.max(first, second));
    System.out.println(Character.toLowerCase('S'));
}
La conclusion correcte de tout est qu’il n’y a pas de magie, il y a une sorte de réalisation. Et tout ne sera pas toujours ce à quoi nous nous attendons. Par exemple, il n'y a pas de packaging : System.out.println("The number is " + 8); L'exemple ci-dessus sera optimisé par le compilateur en une seule ligne. Autrement dit, c’est comme si vous écriviez « Le nombre est 8 ». Et dans l’exemple ci-dessous il n’y aura pas non plus d’emballage :
public static void main(String[] args) {
    System.out.println("The number is " + Math.abs(-2));
}
Comment cela peut-il se produire lorsque nous printlnprenons un objet en entrée et devons d'une manière ou d'une autre connecter les lignes. Des lignes... oui, c'est pour ça qu'il n'y a pas d'emballage en tant que tel. Il Integerexiste des méthodes statiques, mais certaines le sont package. Autrement dit, nous ne pouvons pas les utiliser, mais dans Java lui-même, ils peuvent être activement utilisés. C'est exactement le cas ici. La méthode getChars sera appelée, ce qui crée un tableau de caractères à partir du nombre. Encore une fois, pas de magie, juste Java). Ainsi, dans toute situation peu claire, il suffit d’examiner la mise en œuvre et au moins quelque chose se mettra en place. #Viacheslav
Commentaires
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION