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 primitif | Type enveloppé | Intervalle du cache |
|---|---|---|
| char | Character | [0;127] |
| byte | Byte | [-128;127] |
| short | Short | [-128;127] |
| int | Integer | [-128;127] |
| long | Long | [-128;127] |
| float | Float | Pas de cache |
| double | Double | Pas 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.

envoi en cours...
Le compilateur génère automatiquement un appel à valueOf() pour les constructions de type :
Integer value = 5;
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.