Java Language Piège: utiliser == pour comparer des objets d’emballage primitifs tels que Entier


Exemple

(Ce piège s'applique également à tous les types d’emballages primitifs, mais nous allons l’illustrer pour Integer et int .)

Lorsque vous travaillez avec des objets Integer , il est tentant d'utiliser == pour comparer les valeurs, car c'est ce que vous feriez avec les valeurs int . Et dans certains cas, cela semble fonctionner:

Integer int1_1 = Integer.valueOf("1");
Integer int1_2 = Integer.valueOf(1);

System.out.println("int1_1 == int1_2: " + (int1_1 == int1_2));          // true
System.out.println("int1_1 equals int1_2: " + int1_1.equals(int1_2));   // true

Ici, nous avons créé deux objets Integer avec la valeur 1 et nous les avons Integer (dans ce cas, nous en avons créé un à partir d'un String et un à partir d'un littéral int . Il existe d'autres alternatives). En outre, nous observons que les deux méthodes de comparaison ( == et equals ) produisent toutes deux une valeur true .

Ce comportement change lorsque nous choisissons des valeurs différentes:

Integer int2_1 = Integer.valueOf("1000");
Integer int2_2 = Integer.valueOf(1000);

System.out.println("int2_1 == int2_2: " + (int2_1 == int2_2));          // false
System.out.println("int2_1 equals int2_2: " + int2_1.equals(int2_2));   // true

Dans ce cas, seule la comparaison equals donne le résultat correct.

La raison de cette différence de comportement est que la machine virtuelle Java conserve un cache d’objets Integer compris entre -128 et 127. (La valeur supérieure peut être remplacée par la propriété système "java.lang.Integer.IntegerCache.high" ou la propriété Argument JVM "-XX: AutoBoxCacheMax = size"). Pour les valeurs de cette plage, Integer.valueOf() retournera la valeur mise en cache plutôt que d'en créer une nouvelle.

Ainsi, dans le premier exemple, les Integer.valueOf(1) et Integer.valueOf("1") renvoyé la même instance Integer cache. En revanche, dans le deuxième exemple, Integer.valueOf(1000) et Integer.valueOf("1000") tous deux créé et renvoyé de nouveaux objets Integer .

L'opérateur == pour les types de référence teste l'égalité de référence (c'est-à-dire le même objet). Par conséquent, dans le premier exemple, int1_1 == int1_2 est true car les références sont les mêmes. Dans le deuxième exemple, int2_1 == int2_2 est faux car les références sont différentes.