Utiliser le cache des types enveloppés

Les types enveloppés sont des objets représentants les types primitifs agrémentés de méthodes utilitaires. Parmi celles-ci, la méthode valueOf permet de retourner un type enveloppé à partir d’un type primitif comme le montre l’exemple suivant :

Integer value = Integer.valueOf(5);

En lisant le code source des méthodes valueOf des types enveloppés, je me suis aperçu que celles-ci utilisent un cache contenant un certain nombre de types enveloppés initialisés statiquement au chargement de la classe. Du coup, la méthode valueOf retourne soit un type enveloppé déjà instancié depuis le cache, soit un nouveau type enveloppé.

Voici le code de la méthode valueOf du type enveloppé Character :

public static Character valueOf(char c) {
 if(c <= 127) { // must cache
  return CharacterCache.cache[(int)c];
 }
 return new Character(c);
}

La méthode utilise effectivement un cache dont voici le code :

private static class CharacterCache {
 private CharacterCache(){}
 static final Character cache[] = new Character[127 + 1];
 static {
  for(int i = 0; i < cache.length; i++)
   cache[i] = new Character((char)i);
  }
}

L’utilisation du cache permet de :

  • retourner le type enveloppé plus rapidement par rapport à une création d’un nouvel objet
  • ne pas créer un nouvel objet supplémentaire

Ce tableau liste les types primitifs et enveloppés en indiquant l’utilisation d’un cache avec leur intervalle ou non :

Type primitifType enveloppéIntervalle du cache
charCharacter[0;127]
byteByte[-128;127]
shortShort[-128;127]
intInteger[-128;127]
longLong[-128;127]
floatFloatPas de cache
doubleDoublePas de cache

En conclusion, le code est plus performant pour le temps processeur et plus économique pour la mémoire en utilisant la méthode valueOf pour un type primitif qui est dans l’intervalle du cache. Si ce n’est pas le cas, le type enveloppé sera créé via le constructeur. Finalement, pour obtenir un type enveloppé depuis un type primitif, il est toujours préférable d’utiliser la méthode valueOf.

Commentaires
  • avatar Ugo14 dit :

    Le compilateur génère automatiquement un appel à valueOf() pour les constructions de type :

    Integer value = 5;

    • avatar torrefacteur-express dit :

      Le bytecode généré pour un « Integer value = 5; » fait effectivement un appel à « valueOf ».

      La preuve en image :
      ICONST_5
      INVOKESTATIC java/lang/Integer.valueOf(I)Ljava/lang/Integer;
      ASTORE 1

      Par contre, une nouvelle instance avec un « new » créé un nouvel objet. Du coup, il est vraiment préférable d’utiliser « valueOf » ou « = » qui fait un appel à « valueOf ».

      Merci Ugo14 pour cette précision.

Laisser un commentaire