Question

La combinaison de l'utilisation de types de données primitifs et de leurs classes wrapper respectives, en Java, peut générer de nombreux bogues. L'exemple suivant illustre le problème:

int i = 4;
...
if (i == 10)
  doStuff();

Vous penserez plus tard que vous voulez que la variable i soit définie ou indéfinie. Vous devez donc remplacer l'instanciation ci-dessus par:

Integer i = null;

Maintenant, le contrôle d'égalité échoue.

Est-ce une bonne pratique Java de toujours utiliser les classes de wrapper primitives? De toute évidence, certains bugs seraient résolus tôt, mais quels sont les inconvénients de cela? Cela at-il un impact sur les performances ou l’empreinte mémoire de l’application? Y a-t-il des pièges sournois?

Était-ce utile?

La solution

L'utilisation des types encadrés a des problèmes de performances et de mémoire.

Lors des comparaisons (par exemple, (i == 10) ), Java doit déballer le type avant de faire la comparaison. Même en utilisant i.equals (TEN) utilise un appel de méthode, ce qui est plus coûteux et (IMO) plus laid que la syntaxe ==.

En ce qui concerne la mémoire, l’objet doit être stocké sur le tas (ce qui réduit également les performances) ainsi que la valeur elle-même.

Un piège sournois? i.equals (j) lorsque i est null .

J'utilise toujours les primitives, sauf si elles peuvent être null , mais vérifiez toujours si null avant la comparaison dans ces cas.

Autres conseils

Tout d'abord, passer d'une primitive à l'utilisation d'un objet pour obtenir la possibilité de le définir sur null est probablement une mauvaise décision de conception. Je discute souvent avec mes collègues pour savoir si null est une valeur sentinelle, et j’estime généralement que ce n’est pas le cas (et ne devrait donc pas être interdite comme le devraient les valeurs sentinelles), mais dans ce cas particulier hors de votre façon de l'utiliser comme une valeur sentinelle. S'il vous plaît ne pas. Créez un booléen indiquant si votre entier est valide ou non, ou créez un nouveau type qui enveloppe le booléen et l'entier ensemble.

Habituellement, lors de l'utilisation de versions plus récentes de Java, je constate que je n'ai pas besoin de créer ni d'attribuer explicitement des versions d'objet de primitives en raison de la prise en charge de la boxe automatique qui a été ajoutée à un moment donné dans la version 1.5 (peut-être même dans la version 1.5).

Je suggérerais d'utiliser des primitives tout le temps, sauf si vous avez vraiment le concept de "null".

Oui, la machine virtuelle utilise la substitution automatique et tout le reste à présent, mais cela peut conduire à des cas vraiment étranges dans lesquels vous obtiendrez une exception de pointeur null sur une ligne de code imprévue, et vous devrez commencer faire des contrôles nuls sur chaque opération mathématique. Vous pouvez également commencer à avoir des comportements non évidents si vous commencez à mélanger des types et à obtenir des comportements étranges autoboxing.

Pour les float / doubles, vous pouvez traiter NaN comme nul, mais rappelez-vous que NaN! = NaN, vous devez donc effectuer des vérifications spéciales comme! Float.isNaN (x).

Ce serait vraiment bien s'il y avait des collections qui supportaient les types primitifs au lieu d'avoir à perdre le temps / la surcharge de la boxe.

Dans votre exemple, l'instruction if sera ok jusqu'à ce que vous dépassiez 127 (en tant que liste déroulante automatique de nombres entiers mettra en cache des valeurs allant jusqu'à 127 et renverra la même instance pour chaque nombre jusqu'à cette valeur)

Donc, c'est pire que vous ne le présentez ...

if( i == 10 )

fonctionnera comme avant, mais

if( i == 128 )

va échouer. C’est pour ces raisons que je crée toujours explicitement des objets lorsque j’en ai besoin et que j’ai tendance à nous en tenir aux variables primitives, si possible

Les types de java POD sont là pour une raison. Outre les frais généraux, vous ne pouvez pas effectuer d'opérations normales avec des objets. Un entier est un objet, qui doit être alloué et récupéré. Un int n'est pas.

Si cette valeur peut être vide, vous constaterez peut-être que, dans votre conception, vous avez besoin de quelque chose d'autre.

Il y a deux possibilités - soit la valeur est simplement donnée (le code n'agira pas différemment si elle est remplie ou non), ou indique en fait que vous avez deux types d'objet différents ici (le code agit différemment s'il existe une valeur nulle)

S'il ne s'agit que de données pour l'affichage / le stockage, vous pouvez envisager d'utiliser un véritable DTO - un système qui ne l'a pas du tout comme membre de première classe. Ceux-ci auront généralement un moyen de vérifier si une valeur a été définie ou non.

Si vous recherchez la valeur null à un moment donné, vous souhaiterez peut-être utiliser une sous-classe, car lorsqu'il y a une différence, il y en a généralement plus. Au moins, vous voulez un meilleur moyen d’indiquer votre différence que "if primitiveIntValue == null", cela ne veut vraiment rien dire.

Ne passez pas aux non-primitives uniquement pour obtenir cette installation. Utilisez un booléen pour indiquer si la valeur a été définie ou non. Si vous n'aimez pas cette solution et que vous savez que vos entiers seront dans une limite raisonnable (ou ne vous souciez pas de l'échec occasionnel), utilisez une valeur spécifique pour indiquer «non initialisé», telle que Integer.MIN_VALUE. Mais c'est une solution beaucoup moins sûre que le booléen.

Lorsque vous en êtes arrivé à «plus tard», un peu plus de travail devait être accompli lors de la refactorisation. Utilisez des primitives lorsque cela est possible. (Période capitale) Créez ensuite des POJO si davantage de fonctionnalités sont nécessaires. À mon avis, les classes wrapper primitives sont mieux utilisées pour les données devant être acheminées sur le réseau, c'est-à-dire les applications en réseau. Autoriser les valeurs NULL en tant que valeurs acceptables provoque des maux de tête lorsqu'un système "se développe". Trop de code gaspillé, ou manqué, préservant ce qui devrait être des comparaisons simples.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top