Quand utiliser la classe wrapper et le type primitif

Réponses:

69

D'autres ont mentionné que certaines constructions telles que Collectionsnécessitent des objets et que les objets ont plus de surcharge que leurs homologues primitifs (mémoire et boxe).

Une autre considération est:

Il peut être pratique d'initialiser des objets nullou d'envoyer des nullparamètres dans une méthode / un constructeur pour indiquer l'état ou la fonction. Cela ne peut pas être fait avec des primitives.

De nombreux programmeurs initialisent les nombres à 0 (par défaut) ou -1 pour signifier cela, mais selon le scénario, cela peut être incorrect ou trompeur.

Cela mettra également en scène un NullPointerExceptionmoment où quelque chose est mal utilisé, ce qui est beaucoup plus convivial pour les programmeurs que certains bogues arbitraires sur toute la ligne.

pstanton
la source
15
"Il peut être pratique d'initialiser des objets à null". Cela ne peut pas être pratique car c'est incorrect, si le champ est facultatif, vous devez l'indiquer explicitement.
Eddie Jamsession
8
lol @EddieJamsession merci, je ne m'initialiserai plus jamais à null. (pfffft)
pstanton
@EddieJamsession Si l'initialisation des objets à null comme moyen d'indiquer un échec lors de la définition de la valeur réelle a échoué, comment proposeriez-vous autrement pour attraper ce problème? Oh, je viens de réaliser en tapant ceci: des exceptions. Une NullPointerException est trop générique; il serait préférable d'utiliser des exceptions personnalisées très spécifiques pour indiquer ce qui ne va pas. Bien, je vais le faire à partir de maintenant ...
klaar
1
@EddieJamsession Après avoir lu la question, je suis tombé sur le concept d'un objet facultatif. Droite.
klaar
18

En général, vous devriez utiliser des types primitifs à moins que vous n'ayez besoin d' un objet pour une raison quelconque (par exemple pour mettre dans une collection). Même dans ce cas, envisagez une approche différente qui ne nécessite pas d'objet si vous souhaitez maximiser les performances numériques. Cela est conseillé par la documentation et cet article montre comment l'auto-boxing peut provoquer une grande différence de performances.

Matthew Flaschen
la source
3
le succès des performances n'est pas si grand que la lisibilité / fiabilité du code devrait passer au second plan.
pstanton
2
Premièrement, l'utilisation appropriée des primitives ne rendra pas votre code illisible. Deuxièmement, l'impact sur les performances est important dans certains cas. Il est absurde de dire que cela ne l'est jamais.
Matthew Flaschen
1
@pstanton: veuillez expliquer comment Integerest plus lisible que int.
Stephen C
Dans de nombreux cas, Integer n'est pas plus lisible que int et dans ces cas, j'utiliserai toujours int, ou si je sais qu'une certaine variable ne sera JAMAIS nulle, j'utiliserai int car int est, comme vous l'avez souligné, légèrement plus efficace. Cependant, dans de nombreux cas, il est plus facile pour un autre programmeur de comprendre l'état d'une variable lorsqu'un objet est utilisé, car il peut être initialisé à null pour signifier qu'il n'est pas prêt. Par exemple, si vous avez un enregistrement de base de données non enregistré qui a un identifiant numérique incrémentiel unique, cet identifiant doit-il être 0, -1 ou nul avant de lui attribuer un identifiant valide? Dans ce cas, les objets sont meilleurs.
pstanton
en ce qui concerne les performances - dans des cas particuliers, l'impact sur les performances peut être significatif, c'est-à-dire si vous créez une multitude de ces objets très rapidement ou si beaucoup d'entre eux s'accumulent sur une période de temps. Cependant, je m'attendrais à ce qu'un programmeur décent puisse identifier ces cas spéciaux, soit les éviter, soit les modifier en conséquence. Je n'ai jamais dit que ce n'était JAMAIS significatif, mais en général, ce n'est pas le cas.
pstanton
12

À mon avis, si les membres de ma classe sont des variables wrapper, cela ne dépend pas des valeurs par défaut, ce qui est un comportement convivial pour les développeurs.

1.

class Person {
   int SSN ; // gets initialized to zero by default 
}

2.

class PersonBetter {
  Integer SSN; //gets initialized to null by default
}

Dans le premier cas, vous ne pouvez pas conserver la valeur SSN non initialisée. Cela peut être douloureux si vous ne vérifiez pas si la valeur a été définie avant d'essayer de l'utiliser.

Dans le second cas, vous pouvez garder le SSN initialisé avec null. Ce qui peut conduire à NullPointerException, mais c'est mieux que d'insérer sans le savoir des valeurs par défaut (zéro) en tant que SSN dans la base de données chaque fois que vous essayez de l'utiliser sans initialiser le champ SSN.

Cody
la source
3
Le modèle de constructeur est destiné à contourner ce problème. Dans ce scénario, vous créez un PersonBuilderqui lève une exception si le SSN n'est pas défini avant d'appeler "build" pour obtenir l' Personinstance. Je pense que ce genre de chose est excessif, mais c'est ce que le langage Java promeut pour des modèles appropriés.
Sandy Chapman
8

Je n'utiliserais les types de wrapper que si vous le devez.

En les utilisant, vous ne gagnez pas grand-chose, à part le fait qu'ils le sont Objects.

Et, vous perdez des frais généraux dans l'utilisation de la mémoire et le temps passé à boxer / déballer.

jjnguy
la source
4
vous ne gagnerez peut-être pas grand-chose, mais vous ne perdrez pas non plus beaucoup. sauf si vous utilisez un pilote de paume des années 1990.
pstanton
Le fait qu'ils soient des objets leur donne également beaucoup plus de contexte et d'encapsulation qu'en tant que primitive simple. Vous pouvez donc en fait gagner beaucoup en fonction de ce à quoi ces primitives sont destinées et de l'endroit où elles sont utilisées.
aberrant80
4

Pratiquement j'avais rencontré une situation où l'utilisation de la classe wrapper peut être expliquée.

J'ai créé une classe de service qui avait une longvariable de type

  1. Si la variable est de type long- lorsqu'elle n'est pas initialisée, elle sera définie sur 0 - ce sera déroutant pour l'utilisateur lorsqu'elle sera affichée dans l'interface graphique
  2. Si la variable est de type Long- lorsqu'elle n'est pas initialisée, elle sera définie sur null- cette valeur nulle n'apparaîtra pas dans l'interface graphique.

Cela s'applique Booleanégalement là où les valeurs peuvent être plus déroutantes lorsque nous utilisons une primitive boolean(car la valeur par défaut est false).

Mohamed Afzal
la source
3

Les collections sont le cas typique pour les objets wrapper Java simples. Cependant, vous pouvez envisager de donner au Wrapper une signification plus spécifique dans le code (objet de valeur).

À mon humble avis, il y a presque toujours un avantage à utiliser des objets de valeur quand cela se résume à la lisibilité et à la maintenance du code. L'emballage de structures de données simples à l'intérieur d'objets lorsqu'ils ont certaines responsabilités simplifie souvent le code. C'est quelque chose de très important dans la conception pilotée par domaine .

Il y a bien sûr le problème de la performance, mais j'ai tendance à l'ignorer jusqu'à ce que j'aie la possibilité de mesurer la performance avec des données appropriées et de faire des actions plus dirigées vers la zone problématique. Il peut également être plus facile de comprendre le problème de performances si le code est également facile à comprendre.

Mattias Holmqvist
la source
3

les performances des applications dominées par les calculs numériques peuvent grandement bénéficier de l'utilisation de primitives.

types primitifs, on utilise l'opérateur ==, mais pour le wrapper, le choix préféré est d'appeler la méthode equals ().

"Les types primitifs sont considérés comme nuisibles" parce qu'ils mélangent "la sémantique procédurale dans un modèle orienté objet par ailleurs uniforme.

De nombreux programmeurs initialisent les nombres à 0 (par défaut) ou -1 pour signifier cela, mais selon le scénario, cela peut être incorrect ou trompeur.

Loknath
la source
1

Si vous souhaitez utiliser des collections, vous devez utiliser des classes Wrapper.

Les types primitifs sont utilisés pour les tableaux. De plus, pour représenter des données sans comportement, par exemple, un compteur ou une condition booléenne.

Depuis l'autoboxing, la frontière "quand utiliser une primitive ou un wrapper" est devenue assez floue.

Mais rappelez-vous que les wrappers sont des objets, vous bénéficiez donc de toutes les fonctionnalités Java sophistiquées. Par exemple, vous pouvez utiliser la réflexion pour créer des objets Integer, mais pas des valeurs int. Les classes wrapper ont également des méthodes telles que valueOf.

À M
la source
À part les collections, je ne devrais pas utiliser de classes wrapper? Que diriez-vous de l'utiliser pour une déclaration ordinaire comme Integer i = new Integer (10); Est-ce bien de faire comme ça?
Gopi
l'autoboxing vous permet de faire Integer i = 10;
Tom
1
Non, Sri. Si vous n'êtes pas obligé d'être un objet, n'en faites pas un.
Matthew Flaschen
Autoboxing déballera le i déclaré ci-dessus en int i = 10 ou Integer i = 10?
Gopi
3
int pi = new Integer (10); travaux. Entier oi = 10; travaux. int ni = nul; ne fonctionne pas. le LHS est converti en tout ce que le RHS exige.
pstanton
0

Si vous souhaitez créer un type valeur. Quelque chose comme un ProductSKU ou AirportCode.

Lorsqu'un type primitif (chaîne dans mes exemples) définit l'égalité, vous voudrez remplacer l'égalité.

Chris Missel
la source
5
la chaîne n'est pas une primitive
pstanton
2
il existe encore de bonnes raisons d'encapsuler un type valeur qui contient une chaîne comme objet de base.
Chris Missal
votre réponse n'a tout simplement pas de sens. je ne suis pas sûr de ce que vous dites. Je suis cependant d'accord avec votre commentaire, les classes wrapper sont une bonne idée si elles améliorent la lisibilité.
pstanton
Les types de valeur ou les objets de valeur doivent être créés et être immuables. Par exemple, cela n'aurait pas de sens de créer un objet "CountryCode" comme: new CountryCode ("USA") puis de créer un autre objet de la même manière, où plus tard ils seront différents. Ce ne sont que des chaînes pour commencer, mais elles ont un sens derrière elles. En utilisant des chaînes, vous pouvez les modifier (en ajoutant plus de données, etc.) mais elles ne seraient plus égales. Voir cet article pour une meilleure description de ce que j'essaie d'expliquer :) J'espère que cela a du sens c2.com/cgi/wiki?ValueObject
Chris Missal
0

Les valeurs primitives en Java ne sont pas des objets. Afin de manipuler ces valeurs en tant qu'objet, le package java.lang fournit une classe wrapper pour chacun des types de données primitifs.

Toutes les classes Wrapper sont finales. L'objet de toutes les classes wrapper qui peuvent être initiées est immuable, ce qui signifie que la valeur de l'objet wrapper ne peut pas être modifiée.

Bien que la classe void soit considérée comme une classe wrapper, elle n'englobe aucune valeur primitive et n'est pas initiable. Il n'a pas de constructeur public, il désigne simplement un objet de classe représentant le mot-clé void.

Ahmad Sayeed
la source