Try using it in your preferred language.

English

  • English
  • 汉语
  • Español
  • Bahasa Indonesia
  • Português
  • Русский
  • 日本語
  • 한국어
  • Deutsch
  • Français
  • Italiano
  • Türkçe
  • Tiếng Việt
  • ไทย
  • Polski
  • Nederlands
  • हिन्दी
  • Magyar
translation

Ceci est un post traduit par IA.

제이온

[Effective Java] Évitez la création d'objets inutiles

Choisir la langue

  • Français
  • English
  • 汉语
  • Español
  • Bahasa Indonesia
  • Português
  • Русский
  • 日本語
  • 한국어
  • Deutsch
  • Italiano
  • Türkçe
  • Tiếng Việt
  • ไทย
  • Polski
  • Nederlands
  • हिन्दी
  • Magyar

Texte résumé par l'IA durumis

  • La création d'instances de chaînes de caractères ou de booléens à l'aide du mot-clé new est une perte de mémoire. Il est donc préférable de les déclarer en tant que littéraux ou d'utiliser la méthode Boolean.valueOf().
  • La méthode String.matches() utilise des expressions régulières, ce qui peut entraîner des problèmes de performances. Il est donc conseillé de mettre en cache les instances Pattern pour les réutiliser.
  • Lorsqu'une méthode, comme keySet(), renvoie un objet de vue, il est plus sûr de renvoyer un nouvel objet en utilisant une copie défensive.

Lorsque des objets inutiles sont créés

Utilisation de new String()

String a = new String("hi");
String b = new String("hi");


Les chaînes a, b et c contiendront toutes la chaîne "hi". Cependant, comme les adresses auxquelles ces trois chaînes font référence sont toutes différentes, cela entraîne un gaspillage car des mémoires différentes sont allouées pour les mêmes données.


Untitled


Par conséquent, lors de la déclaration de chaînes, il faut utiliser des littéraux au lieu du mot-clé new.


String a = "hi";
String b = "hi";


Le code source ci-dessus utilise une seule instance. De plus, en utilisant cette méthode, on garantit que tout code utilisant le littéral de chaîne "hi" dans la même JVM réutilisera le même objet. C'est dû à la caractéristique du pool de constantes Java.


Utilisation de new Boolean()

Le code ci-dessus crée une instance Boolean à l'aide d'un constructeur qui prend une chaîne en tant que paramètre. Boolean n'existe que sous la forme de true ou false, et créer une instance à chaque fois est un gaspillage de mémoire. Il est donc préférable d'utiliser la méthode d'usine statique Boolean.valueOf().



Utilisation de String.matches()

S'il est coûteux de créer, il est préférable de mettre en cache et de réutiliser. Cependant, nous ne connaissons pas toujours le coût de l'objet que nous créons. Par exemple, si vous souhaitez écrire une méthode pour vérifier si une chaîne donnée est un nombre romain valide, la meilleure solution est d'utiliser une expression régulière, comme suit.


public static boolean isRomanNumeral(String s) {
    return s.matches("^(?=.)M*(C[MD]|D?C{0,3})(X[CL]|L?X{0,3})(I[XV]|V?I{0,3})$");


Cependant, String.matches() est une méthode qui pose des problèmes de performance. L'instance Pattern créée en interne par cette méthode pour les expressions régulières est utilisée une fois et jetée, devenant rapidement un candidat à la collecte des ordures. Plus la fréquence d'utilisation de l'expression régulière est élevée, plus le coût de création et de suppression de la même instance Pattern est élevé. Il est donc préférable de mettre en cache l'instance Pattern à l'avance et de la réutiliser chaque fois que la méthode isRomanNumeral() est appelée.


public class RomanNumerals {

    private static final Pattern ROMAN = Pattern.compile(
        "^(?=.)M*(C[MD]|D?C{0,3})(X[CL]|L?X{0,3})(I[XV]|V?I{0,3})$");

    public static boolean isRomanNumeral(String s) {
        return ROMAN.matcher(s).matches();
    }


Remarques

Dans tous les exemples ci-dessus, lorsque nous mettons en cache des objets inutiles, nous les avons tous créés comme des objets immuables. C'est pour garantir la sécurité de la réutilisation. Cependant, il existe des cas où cela va à l'encontre de l'intuition de réutiliser des objets immuables.


Un adaptateur (vue) est un objet qui délègue réellement le travail à un objet back-end et qui sert lui-même de deuxième interface. L'adaptateur n'a qu'à gérer l'objet back-end, il suffit donc de créer un seul adaptateur pour chaque objet back-end.


Par exemple, la méthode keySet() de l'interface Map renvoie une vue Set de toutes les clés à l'intérieur de l'objet Map. Les utilisateurs peuvent penser qu'une nouvelle instance Set est créée à chaque fois qu'ils appellent la méthode keySet(), mais en réalité, si l'on regarde la mise en œuvre du JDK, la même instance Set modifiable est renvoyée à chaque fois.


En effet, même si l'instance Set renvoyée est modifiable, les fonctionnalités qu'elle exécute sont toutes les mêmes, et toutes les instances Set représentent l'instance Map. Par conséquent, il n'y a aucun problème si keySet() crée plusieurs objets de vue, mais il n'y a pas besoin de le faire, ni d'avantages à le faire.


public class UsingKeySet {

    public static void main(String[] args) {
        Map menu = new HashMap<>();
        menu.put("Burger", 8);
        menu.put("Pizza", 9);

        Set names1 = menu.keySet();
        Set names2 = menu.keySet();

        names1.remove("Burger");
        System.out.println(names1.size()); // 1
        System.out.println(names2.size()); // 1
    }


Par conséquent, si vous modifiez l'instance names1 comme ci-dessus, l'instance names2 sera également affectée.


Cependant, personnellement, je pense qu'il est plus judicieux que la valeur de retour de la méthode keySet() utilise une copie défensive pour renvoyer un nouvel objet à chaque fois. Si l'instance Set obtenue par la méthode keySet() est également utilisée ailleurs et qu'il existe du code qui modifie l'état de cette instance, on ne peut plus être certain de l'état actuel de l'instance Set et de l'instance Map.


De plus, à moins que keySet() ne soit utilisé de manière excessive, le fait que l'interface Set soit créée à chaque fois n'a pas d'impact significatif sur les performances. Je pense qu'il est préférable de créer l'interface Set comme un objet immuable pour assurer une maintenance stable.


Autoboxing

L'autoboxing est une technique qui convertit automatiquement les types de base et les types d'enveloppe les uns en les autres lorsque les programmeurs mélangent les deux. Cependant, l'autoboxing ne supprime pas complètement la distinction entre les types de base et les types d'enveloppe, il la brouille simplement.


public static long sum() {
    Long sum = 0L;
    for (long i = 0; i <= Integer.MAX_VALUE; i++) {
        sum += i;
    }
    return sum;


Logiquement, il n'y a pas de problème, mais c'est un code très inefficace en termes de performances. La cause en est le type de sum et le type de i dans la boucle for.


Le type de sum est Long et le type de i est long. En d'autres termes, i, qui est de type long, crée une nouvelle instance Long à chaque fois qu'il est ajouté à sum pendant la boucle. En conséquence, il est nécessaire d'utiliser des types de base plutôt que des types d'enveloppe et de faire attention à ne pas utiliser l'autoboxing involontaire.


Points à ne pas confondre

Il ne faut pas mal interpréter l'idée d'éviter la création d'objets inutiles comme signifiant qu'il faut éviter la création d'objets car leur création est coûteuse.


En particulier, dans les JVM modernes, la création et la récupération de petits objets inutiles ne sont pas une tâche très coûteuse. Par conséquent, à moins qu'il ne s'agisse d'objets très coûteux comme les connexions à une base de données, il ne faut pas créer de pool d'objets personnalisé.


De plus, il faut se rappeler que les dommages causés par la réutilisation d'objets lorsque la copie défensive est nécessaire sont beaucoup plus importants que les dommages causés par la création répétée d'objets inutiles. Les effets secondaires de la création répétée n'affectent que la forme du code et les performances, tandis que l'échec de la copie défensive conduit directement aux bogues et aux problèmes de sécurité.


Source

제이온
제이온
제이온
제이온
[Efficace Java] Item 1. Envisager des méthodes d'usine statiques à la place des constructeurs Les méthodes d'usine statiques sont un moyen flexible et efficace de créer des instances à la place des constructeurs. Elles peuvent avoir un nom, renvoyer des instances répondant à des conditions spécifiques et améliorer les performances grâce à la mise

27 avril 2024

[Effective Java] Item 5. Utilisez l'injection de dépendances au lieu de spécifier les ressources Si une classe dépend de ressources externes, il est préférable d'éviter d'utiliser les singletons et les classes utilitaires statiques. L'injection de dépendances peut améliorer la flexibilité, la réutilisabilité et la testabilité de la classe, et l'utili

28 avril 2024

[Effective Java] Item 2. Si vous avez beaucoup de paramètres dans le constructeur, envisagez d'utiliser un générateur Lors de la création d'objets avec un grand nombre de paramètres, l'utilisation du modèle de générateur permet de rendre le code plus propre et plus lisible. Créez un objet générateur avec des paramètres obligatoires, définissez des paramètres optionnels à

27 avril 2024

[Javascript] Structure d'objet (V8) L'objet JavaScript dans le moteur V8 est optimisé comme une structure en fonction de l'état, passant du mode Fast, optimisé comme une structure, au mode Dictionary qui fonctionne comme une table de hachage. Le mode Fast est rapide lorsque les clés et les
곽경직
곽경직
곽경직
곽경직
곽경직

18 mars 2024

[Concurrency] Opération atomique : Clôture de mémoire et ordre de mémoire Ce billet de blog explique comment prendre en compte l'ordre de la mémoire dans les opérations atomiques et l'importance des options d'ordre. Il fournit une description des diverses options d'ordre, telles que Relaxed, Acquire, Release, AcqRel et SecCst,
곽경직
곽경직
곽경직
곽경직
곽경직

12 avril 2024

Comment Rust empêche les bogues de concurrence Rust est un langage puissant qui résout les défis de la programmation concurrente. Son système de types et son modèle de propriété garantissent la sécurité du transfert et du partage de données entre les threads. Les modèles de mutabilité interne, tels qu
곽경직
곽경직
곽경직
곽경직
곽경직

28 mars 2024

[Développeur non spécialisé, survivre en tant que développeur] 16. Conseils pour créer un portfolio de développeur junior Un développeur junior (en particulier un non-spécialiste) doit clairement expliquer les services ou les fonctionnalités qu'il a développés lors de la création d'un portfolio, en plus de ses compétences techniques. Par exemple, si le projet est une « commu
투잡뛰는 개발 노동자
투잡뛰는 개발 노동자
투잡뛰는 개발 노동자
투잡뛰는 개발 노동자

3 avril 2024

Qu'est-ce que JWT (JSON Web Token) ? JSON Web Token (JWT) est un standard ouvert pour la transmission sécurisée d'informations. Il utilise des jetons signés pour garantir l'intégrité et la sécurité des informations. L'en-tête contient le type de jeton et l'algorithme de signature, tandis que
Seize the day
Seize the day
Seize the day
Seize the day
Seize the day

4 mars 2024

[Non-majors, Surviving as Developers] 14. Résumé des questions d'entrevue technique fréquemment posées aux développeurs débutants Guide de préparation aux entrevues techniques pour les développeurs débutants. Zone de mémoire principale, structures de données, RDBMS et NoSQL, programmation procédurale et orientée objet, surcharge et surcharge, algorithmes de remplacement de page, pro
투잡뛰는 개발 노동자
투잡뛰는 개발 노동자
투잡뛰는 개발 노동자
투잡뛰는 개발 노동자

3 avril 2024