La comparaison caractère, entier et types similaires en Java: Utilisation égale ou ==?
Question
Je voulais faire quelque chose que Java: Si j'ai un caractère ou un entier ou un long et ces sortes de choses, dois-je utiliser égale ou == suffisante?
Je sais que avec des chaînes, il n'y a aucune garantie qu'il n'y a qu'une seule instance de chaque chaîne unique, mais je ne suis pas sûr d'autres types boxed.
Mon intuition est d'utiliser égaux, mais je veux vous assurer que je ne perds pas la performance.
La solution
EDIT: La spécification fait certains garanties pour les conversions de boxe. De la section 5.1.7 :
Si la valeur p étant boxed est vrai, faux, un octet, un produit de carbonisation dans la plage \ U0000 à \ u007f, ou un int ou court entre -128 et 127, puis laissez r1 et r2 soient les résultats des deux conversions de boxe de p. C'est toujours le cas où r1 == r2.
La mise en œuvre peut utiliser un plus grand, l'esprit que vous.
Je vraiment éviter l'écriture de code qui repose sur ce bien. Non pas parce qu'il risque d'échouer, mais parce qu'il est pas évident - peu de gens savent les spécifications bien. (Je pensais que précédemment il dépendait de la mise en œuvre.)
Vous devez utiliser equals
ou comparer les valeurs sous-jacentes, i.e..
if (foo.equals(bar))
ou
if (foo.intValue() == bar.intValue())
Notez que même si le autoboxing était garantie d'utiliser des valeurs fixes, d'autres appelants peuvent toujours créer des instances distinctes de toute façon.
Autres conseils
Si vous voulez comparer quoi que ce soit au sujet de la valeur d'un objet, utilisez .equals()
.
Même (et surtout) si ces objets sont les types primitifs wrapper octet, caractère, Short, Integer, Long, float, double et booléennes.
« ==
» ne compare jamais l'identité de l'objet et vous qui est très, très rarement ce que vous voulez. Et de fait jamais ce que vous voulez avec les emballages primitifs.
Utilisez uniquement ==
dans un de ces deux scénarios:
- toutes les valeurs participant à la comparaison sont des types primitifs (et de préférence non nombres à virgule flottante)
- vous voulez vraiment savoir si deux références se réfèrent au même objet (ce qui inclut la comparaison des
enum
s, parce qu'il ya la valeur est liée à l'identité de l'objet)
//Quick test
public class Test {
public static void main(String[] args) {
System.out.println("Are they equal? "+ (new Long(5) == new Long(5)));
}
}
Sortie:
"Sont-ils égaux? 0"
Réponse:
Non, ils ne sont pas égaux. Vous devez utiliser .equals ou comparer leurs valeurs primitives.
Si la valeur p étant boxed est vrai, faux, un octet, un produit de carbonisation dans la plage \ U0000 à \ u007f, ou un int ou court entre -128 et 127, puis laissez r1 et r2 soient les résultats des deux conversions de boxe de p. C'est toujours le cas où r1 == r2.
et
Discussion
Idéalement, la boxe une primitive donnée valeur p, serait toujours donner un référence identique. En pratique, cela, peut ne pas être réalisable à l'aide existante techniques de mise en œuvre. Les règles ci-dessus sont un compromis pragmatique. le clause finale exige que ci-dessus certaines valeurs communes sont toujours mis en boîte en objets impossibles à distinguer. le la mise en œuvre peut mettre en cache ces derniers, paresseusement ou avec impatience.
Pour d'autres valeurs, cette formulation toutes les hypothèses sur ne permettant pas la identité des valeurs sur la boxed part du programmeur. Cela permettrait (Mais pas besoin) le partage d'une partie ou toutes ces références.
Cela garantit que, dans le plus courant des cas, le comportement sera le une souhaitée, sans imposer une excessive pénalité de performance, en particulier sur petits appareils. Moins de mémoire limitée mises en œuvre pourraient, par exemple, cache tous les caractères et courts métrages, comme ainsi que des entiers et désire ardemment dans la gamme de -32K -. + 32K
Ainsi, dans certains cas, == travaillera, dans beaucoup d'autres, il ne sera pas. Utilisez toujours .equals pour être sûr puisque vous ne pouvez pas le concessionnaire d'(généralement) la façon dont les cas ont été obtenus.
Si la vitesse est un facteur (la plupart .equals commencent par une comparaison ==, ou du moins ils le devraient) et vous pouvez gurantee comment ils ont été alloués et ils se situent dans les plages ci-dessus alors == est sûr.
Certaines machines virtuelles peut augmenter cette taille, mais il est plus sûr d'assumer la plus petite taille tel que spécifié par la spécification langauge que de compter sur un comportement VM particulier, à moins que vous vraiment vraiment vraiment besoin.
Implémentations des égaux méthode (Object o) commencent presque toujours avec
if(this == o) return true;
en utilisant equals
même si ==
est vrai est vraiment pas beaucoup d'un coup de performance.
Je recommande toujours * en utilisant la méthode equals
sur les objets.
* Bien sûr, il y a très peu de moments où vous ne devriez pas prendre ce conseil.
La réponse générale est pas , vous n'êtes pas garanti que, pour la même valeur numérique, les objets longs que vous obtenez sont les mêmes (même si vous vous limiter à l'aide Long.valueOf ()).
Cependant, il est possible que vous obtiendrez une amélioration de la performance en essayant d'abord de tester l'égalité des références (en utilisant ==), puis, en cas d'échec, essayant equals (). Tout dépend des coûts comparatifs du test == supplémentaire et l'appel de méthode ... Votre kilométrage peut varier, mais il vaut la peine d'essayer un simple test en boucle pour voir ce qui est mieux.
Il convient de noter que les valeurs auto-boxed seront mis en commun les utilisations objet si elles sont disponibles. Ceci est la raison pour laquelle (entier) 0 == (entier) 0 mais (entier) 128! = (Entier) 128 pour Java 6u13
J'aime voir visuellement le résultat:
public static void main(String[] args)
{
Integer a = 126; //no boxed up conversion, new object ref
Integer b = 126; //no boxed up conversion, re-use memory address
System.out.println("Are they equal? " + (a == b)); // true
Integer a1 = 140; //boxed up conversion, new object
Integer b1 = 140; //boxed up conversion, new object
System.out.println("Are they equal? " + (a1 == b1)); // false
System.out.println("Are they equal? " + (new Long(5) == new Long(5))); // false
}
==
compare la référence de l'objet alors que equals(Object obj)
compare l'égalité des objets. S'il n'y a jamais plus d'une instance d'un égal objet existant vous doit utilisation equals
pour la comparaison de l'égalité.
Exemples:
Integer i1 = new Integer(12345);
Integer i2 = new Integer(12345);
ce sont les différentes instances d'objet, mais sont égaux selon l'égalité de nombre entier, vous devez donc utiliser equals(Object obj)
public enum Gender {
MALE, FEMALE;
}
dans ce cas, il n'y aura qu'un seul exemple de FEMALE
existe donc ==
est sûr à utiliser.