Est-ce une mauvaise pratique de créer de nouveaux objets sans les stocker?


23

J'ai vu des objets créés en code Java sans stocker une référence à l'objet. Par exemple, dans un plugin Eclipse, j'ai vu un SWT Shell créé comme suit:

new Shell();

Ce nouvel objet Shell n'est pas stocké dans une variable, mais restera référencé jusqu'à ce que la fenêtre soit supprimée, ce qui [je crois?] Se produit par défaut lorsque la fenêtre est fermée.

Est-ce une mauvaise pratique de créer des objets comme celui-ci sans y stocker une référence? Ou la bibliothèque était-elle mal conçue? Et si je n'ai pas besoin d'une référence, mais que je veux seulement les "effets secondaires" de l'objet? Dois-je quand même enregistrer une référence?

MISE À JOUR:

Certes, mon exemple ci-dessus est pauvre. Bien que j'aie vu des éléments d'interface utilisateur créés comme celui-ci, la création d'un shell SWT comme celui-ci serait probablement inutile car vous devez appeler la méthode open sur l'instance Shell. Il y a de meilleurs exemples fournis par aix tels que les suivants du tutoriel de concurrence Java :

(new HelloThread()).start();

Cette pratique est observée dans de nombreux contextes, de sorte que les questions demeurent. Est-ce une bonne pratique?


2
À quoi servirait le stockage de la référence?
Daniel R Hicks

(Il serait probablement préférable, d'un point de vue conceptuel, d'avoir une méthode statique telle que Shell.createTopLevelShell()ou quoi que ce soit, par rapport à l'utilisation d'un constructeur dans ce cas. Mais fonctionnellement il y a peu de différence.)
Daniel R Hicks

S'agit-il de la pratique de créer des objets sans s'y référer, de créer des classes qui nécessitent cette pratique, ou s'agit-il spécifiquement de la façon dont SWT utilise ce type de modèle?
StriplingWarrior

1
Les objets SWT doivent être dispose()d: Règle 1: Si vous les avez créés, vous les supprimez. eclipse.org/articles/swt-design-2/swt-design-2.html
jbindel

2
J'utiliserais une variable pour contenir une référence à des fins de débogage. Si vous avez un point d'arrêt dans cette méthode, vous pouvez demander au débogueur d'interroger l'objet via la variable locale. Sans la référence, je suis sûr que c'est possible mais probablement beaucoup plus difficile.
Martin York

Réponses:


12

Il y a un élément de préférence personnelle à cela, mais je pense que ne pas stocker la référence n'est pas nécessairement une mauvaise pratique.

Prenons l'exemple hypothétique suivant:

new SingleFileProcessor().process(file);

Si un nouvel objet processeur doit être créé pour chaque fichier et n'est pas nécessaire après l' process()appel, il ne sert à rien d' en stocker une référence.

Voici un autre exemple, tiré du didacticiel de concurrence Java :

(new HelloThread()).start();

J'ai vu de nombreux autres exemples lorsque la référence n'est pas stockée, et qui se lisaient parfaitement bien à mes yeux, tels que:

String str = new StringBuilder().append(x).append(y).append(z).toString();

(L' StringBuilderobjet n'est pas conservé.)

Il existe des modèles similaires impliquant common.lang's HashCodeBuilderet al.


2
@BalusC: Avec respect, je ne vois pas ce qui le rend louche et de quelle manière avoir une méthode d'usine est mieux (je suppose que votre exemple est analogue au mien, et getInstance()est une usine et non un singleton).
NPE

Il appartient à l'usine d'utiliser ou non un singleton. L'appelant de l'usine ne devrait pas trop y penser.
Donal Fellows

Dans votre exemple, l'instance FileProcessor n'est (vraisemblablement) pas nécessaire une fois l'instruction terminée, tandis que dans l'exemple OP, l'instance Shell est (sous les couvertures) référencée par un autre objet, et cette référence (et donc l'objet Shell) persiste au-delà de la durée de la déclaration.
Daniel R Hicks

@BalusC: FileProcessor pourrait avoir des méthodes supplémentaires pour modifier le comportement de process.
kevin cline

7

Si vous n'avez pas besoin d' une référence à l'objet créé, ne vous accrochez pas à la référence. C'est aussi simple que ça.


5

En général, il est recommandé de publier les références aussi rapidement que possible. Je ne vois aucune différence entre:

HelloThread thread = new HelloThread();
thread.start();
// where thread is never used for the rest of the method

et

(new HelloThread()).start();

En ce qui concerne le code, vous évitez simplement d'utiliser un nom de variable, ce qui pourrait être une chose positive. Le compilateur JIT est généralement assez intelligent pour reconnaître qu'il peut récupérer le thread après sa dernière utilisation, il n'y a donc probablement aucune différence du point de vue des performances.

Le seul vrai problème à éviter est le code dans le constructeur Anti-Pattern , mais il ne semble pas que ce soit ce que vous demandez.


3

Cela peut être mauvais si vous utilisez SWT, car vous devez nettoyer après vous-même (en appelant la méthode dispose ()). Mais pour les autres classes (non SWT) ça va.

Voici un article sur la gestion des ressources du système d'exploitation


Les références circulaires n'empêchent pas les objets d'être récupérés dans Java. Toute machine virtuelle Java moderne détermine si les objets sont GCables en fonction de leur accessibilité et n'utilise pas le comptage des références.
jbindel

2
En effet, il n'utilise pas le comptage de références. Mais SWT est un cas spécial où nous avons besoin d'appeler dispose (), bien qu'il n'y ait pas besoin d'appeler tout premier keep ().
Alex

Je voulais me référer uniquement au cas non SWT.
jbindel

Voici un article sur la gestion des ressources du système d'exploitation eclipse.org/articles/swt-design-2/swt-design-2.html
Alex

2
Dans ce cas, modifiez votre réponse pour supprimer la déclaration «impossible au GC» car elle est trompeuse.
Donal Fellows

1

Tout d'abord, vous allez ennuyer les gens qui ont appris le C ou le C ++ avant Java. Je vais laisser cela comme un exercice pour que le lecteur décide si c'est un pour ou un contre.

Bien qu'il existe certainement des situations dans lesquelles les objets sont conçus pour être de très courte durée, la plupart du temps si quelque chose est suffisamment complexe pour créer un objet, il est suffisamment complexe pour avoir de bonnes raisons de conserver une référence, donc ne pas le conserver devrait être au moins un avertissement pour vérifier si vous avez oublié quelque chose.

Par exemple, dans un didacticiel, personne ne se soucie de conserver une référence de thread, mais dans la vie réelle, si quelque chose prend suffisamment de temps pour que vous souhaitiez générer un thread, cela prend généralement assez de temps pour que vous puissiez être en mesure d'annuler le thread. Ou si la durée de vie est plus courte, vous générez généralement un tas de fils que vous voudrez joinavant de continuer. Ou vous voulez vous assurer que la création de votre thread a bien réussi. Ou vous voulez vous assurer que le fil se termine proprement avant de quitter. Vous obtenez l'image.


2
Le souci des programmeurs ennuyeux d'autres langues est-il vraiment la première préoccupation?
Buttons840

Cela en fait un problème de lisibilité / familiarité / style en fonction de la composition de votre équipe, car c'est un style que beaucoup de gens véhiculent. Même les personnes qui n'ont jamais programmé en C ++ adoptent souvent des styles de leurs mentors qui l'ont fait.
Karl Bielefeldt
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.