J'utilisais Sonar pour rendre mon code plus propre, et il a été signalé que j'utilise new Integer(1)
au lieu de Integer.valueOf(1)
. Comme il semble que valueOf
n'instancie pas un nouvel objet, la mémoire est plus conviviale. Comment valueOf
ne peut pas instancier un nouvel objet? Comment ça marche? Est-ce vrai pour tous les entiers?
Réponses
Trop de publicités?Integer.valueOf implémente un cache pour les valeurs -128 à +127. Voir le dernier paragraphe de la spécification du langage Java, section 5.1.7, qui explique les conditions requises pour la boxe (généralement implémenté en termes de méthodes .valueOf).
http://docs.oracle.com/javase/specs/jls/se7/html/jls-5.html#jls-5.1.7
À partir de la JavaDoc:
public static Entier valueOf(int i) Retourne un Entier instance représentant le spécifiée valeur int. Si un nouveau Entier instance n'est pas nécessaire, cette méthode doit généralement être utilisés de préférence pour le constructeur de type Entier(int), que cette méthode est susceptible d'avoir nettement mieux l'espace et le temps de la performance par la mise en cache souvent demandé valeurs.
ValueOf
est généralement utilisé pour l'autoboxing et donc (quand il est utilisé pour l'autoboxing) met en cache au moins des valeurs de -128 à 127 pour suivre l'autoboxing la spécification.
Voici l' valueOf
de la mise en œuvre de Sun JVM 1.5.? Jetez un oeil à l'ensemble de la classe pour voir comment le cache est initialisé.
public static Integer valueOf(int i) {
final int offset = 128;
if (i >= -128 && i <= 127) { // must cache
return IntegerCache.cache[i + offset];
}
return new Integer(i);
}
ils sont vous pousse à utiliser valueOf()
au lieu de new Integer()
de sorte que la méthode de valueOf()
fait pour vous, et des caches de la valeur dans le cas où vous souhaitez obtenir le même nombre de nouveau à l'avenir. Dans ce cas, la méthode ne démarrent des instances new Integer, mais vous donnera le cache, ce qui va faire de "création" de new Integer beaucoup plus rapide et la mémoire conviviale..
De cette façon, vous pouvez vous entraîner vous-même beaucoup de problèmes si vous êtes inexpérimenté programmeur java puisque vous en conclure qu' Integer.valueOf(342)==Integer.valueOf(342)
, parce que vous pouvez (ou pas) ont le même pointeur de deux Entiers, et sans doute vous allez le pratiquer d'une manière, disons, vous avez appris en C#, donc qui va vous montrer les bugs de temps en temps, et vous ne savez pas comment et où ceux-ci venaient de...
À partir du code source java.lang.Integer. Le cache entier est configurable. Pour configurer la taille du cache Integer autre que Sun, nous devons utiliser la propriété système java.lang.Integer.IntegerCache.high
selon le code source.
/**
* Cache to support the object identity semantics of autoboxing for values between
* -128 and 127 (inclusive) as required by JLS.
*
* The cache is initialized on first usage. During VM initialization the
* getAndRemoveCacheProperties method may be used to get and remove any system
* properites that configure the cache size. At this time, the size of the
* cache may be controlled by the vm option -XX:AutoBoxCacheMax=<size>.
*/
// value of java.lang.Integer.IntegerCache.high property (obtained during VM init)
private static String integerCacheHighPropValue;
static void getAndRemoveCacheProperties() {
if (!sun.misc.VM.isBooted()) {
Properties props = System.getProperties();
integerCacheHighPropValue =
(String)props.remove("java.lang.Integer.IntegerCache.high");
if (integerCacheHighPropValue != null)
System.setProperties(props); // remove from system props
}
}
private static class IntegerCache {
static final int high;
static final Integer cache[];
static {
final int low = -128;
// high value may be configured by property
int h = 127;
if (integerCacheHighPropValue != null) {
// Use Long.decode here to avoid invoking methods that
// require Integer's autoboxing cache to be initialized
int i = Long.decode(integerCacheHighPropValue).intValue();
i = Math.max(i, 127);
// Maximum array size is Integer.MAX_VALUE
h = Math.min(i, Integer.MAX_VALUE - -low);
}
high = h;
cache = new Integer[(high - low) + 1];
int j = low;
for(int k = 0; k < cache.length; k++)
cache[k] = new Integer(j++);
}
private IntegerCache() {}
}
À partir de java.lang.Short, java.lang.Byte et java.lang.Long créent un cache de 127 à -128.
private static class LongCache {
private LongCache(){}
static final Long cache[] = new Long[-(-128) + 127 + 1];
static {
for(int i = 0; i < cache.length; i++)
cache[i] = new Long(i - 128);
}
}
private static class ShortCache {
private ShortCache(){}
static final Short cache[] = new Short[-(-128) + 127 + 1];
static {
for(int i = 0; i < cache.length; i++)
cache[i] = new Short((short)(i - 128));
}
}
private static class ByteCache {
private ByteCache(){}
static final Byte cache[] = new Byte[-(-128) + 127 + 1];
static {
for(int i = 0; i < cache.length; i++)
cache[i] = new Byte((byte)(i - 128));
}
}