Quand utiliser la primitive et quand les types de référence en Java
10 réponses
dans ce cas, vous devez utiliser primitif types (
int
) ou types de référence (Integer
)?
en règle générale, j'utiliserai une primitive (comme int
) à moins que je doive utiliser une classe qui enveloppe une primitive.
L'un des cas où il fallait utiliser une classe d'emballage telle que Integer
est dans le cas de l'utilisation de génériques , car Java ne supporte pas l'utilisation de les types primitifs comme paramètres de type:
List<int> intList = new ArrayList<int>(); // Not allowed.
List<Integer> integerList = new ArrayList<Integer>(); // Allowed.
et, dans de nombreux cas, je vais profiter de autoboxing and unboxing , de sorte que je n'ai pas à effectuer explicitement conversions des primitifs à sa classe d'emballage et vice versa:
// Autoboxing will turn "1", "2", "3" into Integers from ints.
List<Integer> numbers = Arrays.asList(1, 2, 3);
int sum = 0;
// Integers from the "numbers" List is unboxed into ints.
for (int number : numbers) {
sum += number;
}
aussi, comme note supplémentaire, lors de la conversion des primitives à ses objets de classe wrapper, et les instances uniques d'objets ne sont pas nécessaires, utilisez la méthode valueOf
fourni par la méthode wrapper, car il effectue la mise en cache et renvoie la même instance pour une certaine valeur, réduisant le nombre d'objets qui sont créés:
Integer i1 = Integer.valueOf(1); // Prefer this.
Integer i2 = new Integer(1); // Avoid if not necessary.
pour plus d'information sur les méthodes valueOf
, la spécification API pour la méthode Integer.valueOf
peut servir de référence pour la façon dont ces méthodes se comporteront dans les classes d'enrubannage pour les primitifs.
cela dépend vraiment du contexte. D'abord préférer le primitif, parce qu'il est plus intuitif et a moins de frais généraux. Si cela n'est pas possible pour des raisons génériques/d'autoboxing, ou si vous voulez qu'il soit nul, alors optez pour le type wrapper (type complexe comme vous l'appelez).
les règles générales que je respecte lors de la création d'une API peuvent être résumées comme suit:
- si la méthode doit retourner une valeur, utiliser un type primitif
- si la méthode ne s'applique pas toujours (par exemple: getRadioId(...) sur un objet où un tel ID peut ne pas exister), alors renvoie un entier et spécifie dans les JavaDocs que la méthode retournera null dans certains cas.
sur #2, attention pour les Npe lorsque l'autoboxing. Si vous avez une méthode définie comme:
public Integer getValue();
et appelez - le comme suit:
int myValue = getValue();
dans le cas où getValue() renvoie null, vous obtiendrez un NPE sans cause évidente.
ma règle de base est la suivante: n'utilisez les primitives boxées que lorsqu'il est nécessaire d'obtenir le code à compiler. Les seuls endroits dans votre code où les noms des classes d'enrubannage primitives doivent apparaître sont les paramètres de type génériques et les appels de méthode statiques:
List<Integer> intList = new ArrayList<Integer>();
int n = Integer.parseInt("123");
C'est le conseil que je donnerais aux nouveaux programmeurs Java. Au fur et à mesure qu'ils en apprennent davantage, ils se retrouvent dans des situations où ils doivent faire preuve de plus de discernement, comme lorsqu'ils doivent traiter avec des cartes ou des bases de données, mais en ils devraient aussi avoir une meilleure compréhension de la différence entre les primitifs et les primitifs en boîte.
nous incite à croire que int
et Integer
(par exemple) sont interchangeables, mais c'est un piège. Si vous mélangez les deux types de valeur indistinctement, vous pouvez finir par comparer deux valeurs entières avec ==
ou essayer de déballer un null
sans s'en rendre compte. Les bogues qui en résultent peuvent être intermittents et difficiles à repérer.
il n'aide pas que la comparaison des primitives boxées avec ==
parfois fonctionne comme si elle faisait une comparaison de valeur. C'est une illusion causée par le fait que les valeurs à l'intérieur d'une certaine plage sont automatiquement cachées dans le processus d'autoboxing. C'est le même problème que nous avons toujours eu avec les valeurs String: les comparer avec ==
parfois "fonctionne" parce que vous comparez en fait deux références à la même, objet caché.
en traitant avec des cordes, nous pouvons juste dire au n00bs de ne jamais les comparer avec ==
, comme nous l'avons fait tout au long. Mais comparer des primitives avec ==
est parfaitement valide; le truc (grâce à l'autoboxing) est d'être sûr que les valeurs sont vraiment primitives. Le compilateur va maintenant nous laisser déclarer une variable comme un Integer
et l'utiliser comme si c'était un int
; cela signifie que nous devons exercer un plus grand niveau de discipline et le traiter comme une erreur quand quelqu'un ne le faire sans une bonne raison.
depuis Java fait quelque chose appelé auto-boxe et auto-unboxing , vous devriez utiliser le type primitif int
dans la plupart des cas en raison de moins de frais généraux.
la seule fois où vous avez absolument besoin d'utiliser Integer est en génériques.
List<int> list; // won't compile
List<Integer> list; // correct
plutôt que de les appeler "types complexes", vous seriez mieux servi en pensant Entier, Double, etc. comme "Classes", et int, double, etc. comme "primitives".
si vous faites n'importe quel type de mathématiques sophistiquées, la représentation numérique basée sur la classe comme le nombre entier et le Double sera encombrante et vous ralentira-beaucoup d'opérations mathématiques peuvent seulement être faites avec des primitives.
, d'autre part, si vous essayez de mettre vos numéros dans des collections comme Listes et Cartes, Ces collections ne peuvent contenir que des objets - et donc vous devez utiliser (ou convertir en) des classes comme entier et Double.
personnellement, j'utilise des primitives chaque fois que je peux m'en sortir, et ne convertit en représentations de classe comme Integer quand il est temps de faire des entrées ou des sorties, et le transport nécessite ces représentations.
cependant, si vous ne faites pas de calcul du tout, et à la place sont tout simplement passer les valeurs directement à travers votre code, vous pourriez vous épargner quelques problèmes en traitant les formes basées sur la classe (comme Integer) exclusivement.
Je ne pense pas qu'il y ait de règle en tant que telle. Je choisirais les types plutôt que les primitives (Integer sur int) quand j'écris des signatures de méthode, des cartes, des collections, des objets de données qui se transmettent. En tant que tel, je voudrais toujours utiliser entier au lieu de int, même à l'intérieur des méthodes etc. Mais si vous pensez que c'est trop d'ennui (pour taper extra "eger") alors il est correct d'utiliser les ints pour les variables locales.
si vous voulez que setAttribute à session vous devez utiliser objet comme entier,booléen,chaîne dans les servlets. Si vous souhaitez utiliser la valeur, vous pouvez utiliser les types primitifs. Les objets peuvent être nuls, mais pas les primitifs. Et si vous voulez comparer les types pour les primitives, utilisez == mais les objets utilisent .égal parce que dans la comparaison d'objet = = looks not values il regarde si ce sont les mêmes objets. Et utiliser des primitives accélère le code.
un cas dans lequel Integer
pourrait être préféré est lorsque vous travaillez avec une base de données où les entrées numériques sont autorisées à être null, puisque vous ne seriez pas en mesure de représenter une valeur nulle avec un int
.
mais bien sûr si vous faites des maths droites, alors int
serait mieux comme d'autres l'ont mentionné en raison de l'intuition et moins de frais généraux.
je pense que c'est un peu tard, mais je voulais ajouter mon avis, juste au cas où.
dans certains scénarios, il est nécessaire d'utiliser les wrappers comme l'absence de valeur est différente de la valeur par défaut.
exemple, pour un projet sur lequel j'ai travaillé, il y avait un champ à l'écran où l'utilisateur pouvait entrer une double valeur, l'exigence opérationnelle mentionnait clairement que si l'utilisateur entre un 0 la signification est différente de ne pas entrer une valeur et de quitter le champ vide et cette différence va avoir un impact plus tard dans un autre module. donc dans ce scénario nous avons dû utiliser L'objet Double, puisque je ne peux pas représenter un manque de valeur en utilisant la primitive; puisque la primitive sera par défaut à 0 qui était une entrée valide pour le champ.