Il est beaucoup plus pratique et plus propre d’utiliser une seule déclaration telle que
import Java.awt.*;
que d'importer un tas de classes individuelles
import Java.awt.Panel;
import Java.awt.Graphics;
import Java.awt.Canvas;
...
Quel est le problème avec l'utilisation d'un caractère générique dans l'instruction import
?
Le seul problème est qu'il encombre votre espace de noms local. Par exemple, supposons que vous écriviez une application Swing et que vous ayez besoin de Java.awt.Event
, et que vous interfaciez également avec le système de calendrier de l'entreprise, qui a com.mycompany.calendar.Event
. Si vous importez les deux à l'aide de la méthode générique, l'une des trois choses suivantes se produit:
Java.awt.Event
et com.mycompany.calendar.Event
et vous ne pouvez même pas compiler..*
), mais c'est la mauvaise et vous avez du mal à comprendre pourquoi votre code prétend que le type est incorrect.com.mycompany.calendar.Event
, mais quand ils en ajoutent un, votre code précédemment valide cesse soudainement de compiler.L'avantage de lister explicitement toutes les importations est que je peux dire en un coup d'œil quelle classe vous vouliez utiliser, ce qui facilite simplement la lecture du code. Si vous faites simplement une chose ponctuelle, il n'y a rien explicitement faux , mais les futurs responsables vous remercieront pour votre clarté sinon.
Voici un vote pour étoiles importations. Une instruction d'importation est destinée à importer un package, pas une classe. Il est beaucoup plus propre d'importer des paquets entiers; les problèmes identifiés ici (par exemple, Java.sql.Date
vs Java.util.Date
) sont facilement résolus par d'autres moyens, et non pas {vraiment} par des importations spécifiques et ne justifient certainement pas des importations incroyablement pédantes sur toutes les classes. Il n’y a rien de plus déconcertant que d’ouvrir un fichier source et de devoir parcourir 100 déclarations d’importation.
Faire des importations spécifiques rend le refactoring plus difficile; si vous supprimez/renommez une classe, vous devez supprimer tout de ses importations spécifiques. Si vous passez d'une implémentation à une classe différente dans le même package, vous devez réparer les importations. Bien que ces étapes supplémentaires puissent être automatisées, elles constituent un véritable gage de productivité sans réel gain.
Même si Eclipse n'effectuait pas d'importation de classe par défaut, tout le monde continuerait à importer en étoile. Je suis désolé, mais il n'y a vraiment aucune justification rationnelle pour faire des importations spécifiques.
Voici comment gérer les conflits de classes:
import Java.sql.*;
import Java.util.*;
import Java.sql.Date;
veuillez consulter mon article L'importation à la demande, c'est le mal
En bref, le plus gros problème est que votre code peut casser lorsqu'une classe est ajoutée à un paquet que vous importez. Par exemple:
import Java.awt.*;
import Java.util.*;
// ...
List list;
En Java 1.1, c'était très bien. La liste a été trouvée dans Java.awt et il n'y a pas eu de conflit.
Supposons maintenant que vous archiviez votre code qui fonctionne parfaitement et qu'un an plus tard, quelqu'un d'autre l'apporte pour le modifier et utilise Java 1.2.
Java 1.2 a ajouté une interface nommée List à Java.util. BOOM! Conflit. Le code qui fonctionne parfaitement ne fonctionne plus.
Ceci est une fonctionnalité du langage EVIL. Il y a NO raison pour laquelle le code doit cesser de compiler simplement parce qu'un type est ajouté à un paquet ...
En outre, il est difficile pour un lecteur de déterminer quel "Foo" vous utilisez.
C'est pas mauvais d'utiliser un caractère générique avec une instruction d'importation Java.
Dans Clean Code , Robert C. Martin recommande en fait de les utiliser pour éviter les longues listes d'importation.
Voici la recommandation:
J1: Évitez les longues listes d'importation en utilisant Wildcards
Si vous utilisez deux classes ou plus d'un package, puis importez le package complet avec
package d'importation. *;
Les longues listes d’importations sont décourageantes pour le lecteur. Nous ne voulons pas encombrer les sommets de nos modules avec 80 lignes d'importations. Nous voulons plutôt le les importations doivent être une déclaration concise sur quels paquets nous collaborons avec.
Les importations spécifiques sont difficiles dépendances, alors que les importations génériques ne sont pas. Si vous importez spécifiquement un fichier classe, alors cette classe doit exister. Mais si vous importez un package avec un wildcard, pas besoin de classes particulières exister. La déclaration d'importation simplement ajoute le package au chemin de recherche lors de la recherche de noms. Donc, pas vrai la dépendance est créée par de telles importations, et ils servent donc à garder notre modules moins couplés.
Il y a des moments où la longue liste de des importations spécifiques peuvent être utiles. Pour exemple, si vous avez affaire à code hérité et que vous voulez savoir Quelles sont les classes dont vous avez besoin pour construire des simulacres et bouts pour, vous pouvez marcher le liste des importations spécifiques à découvrir les vrais noms qualifiés de tous ceux classes et ensuite mettre le approprié talons en place. Cependant, cette utilisation pour les importations spécifiques sont très rares . En outre, la plupart des IDE modernes le seront vous permet de convertir le caractère générique importations à une liste d'importations spécifiques avec une seule commande. Donc même dans le cas, il est préférable d’importer joker.
Les importations génériques peuvent parfois causer conflits de noms et ambiguïtés. Deux classes avec le même nom, mais en différents paquets, devront être spécifiquement importé, ou au moins spécifiquement qualifié lorsqu'il est utilisé. Ce peut être une nuisance mais est assez rare que l’utilisation d’importations génériques est toujours généralement mieux que spécifique importations.
Il encombre votre espace de noms et vous oblige à spécifier tous les noms de classe ambigus. L'occurrence la plus commune de ceci est avec:
import Java.util.*;
import Java.awt.*;
...
List blah; // Ambiguous, needs to be qualified.
Cela aide également à rendre vos dépendances concrètes, car toutes vos dépendances sont listées en haut du fichier.
Performance : Aucun impact sur les performances car le code octet est identique . Cependant, cela entraînera des frais généraux de compilation.
Compilation : sur ma machine personnelle, Compiler une classe vide sans rien importer prend 100 ms, mais la même classe lors de l'importation Java. * Prend 170 ms.
La plupart des endroits où j'ai travaillé et qui utilisent une quantité importante de Java font des importations explicites une partie de la norme de codage. J'utilise parfois encore * pour le prototypage rapide, puis je développe les listes d'importation (certains IDE le feront aussi pour vous) lors de la production du code.
Je préfère les importations spécifiques, car cela me permet de voir toutes les références externes utilisées dans le fichier sans regarder l'ensemble du fichier. (Oui, je sais que cela ne montrera pas nécessairement les références complètes. Mais je les évite autant que possible.)
Dans un projet précédent, j'avais constaté que le passage des importations * à des importations spécifiques réduisait de moitié le temps de compilation (d'environ 10 minutes à environ 5 minutes). Le * -import amène le compilateur à rechercher dans chacun des packages répertoriés une classe correspondant à celle que vous avez utilisée. Bien que cette période puisse être réduite, elle s’additionne pour les grands projets.
Un effet secondaire de * -import était que les développeurs copiaient et collaient les lignes d'importation courantes plutôt que de réfléchir à ce dont ils avaient besoin.
Dans Livre DDD
Quelle que soit la technologie de développement sur laquelle la mise en œuvre sera basée, cherchez des moyens de réduire au minimum la vulnérabilité travail de refactoring MODULES. En Java, il n’est pas impossible d’importer dans des classes individuelles, mais vous peut au moins importer des packages entiers à la fois, reflétant ainsi l’intention que les packages soient des unités très cohérentes tout en réduisant simultanément l'effort de changer les noms de paquets.
Et si elle encombre l'espace de noms local, ce n'est pas votre faute - blâmez la taille du paquet.
Parmi tous les arguments valables des deux côtés, je n’ai pas trouvé la principale raison pour éviter le caractère générique: j’aime pouvoir lire le code et savoir directement ce que chaque classe est, ou si sa définition n’est pas dans le langage le fichier, où le trouver. Si plus d'un paquet est importé avec *, je dois aller les chercher tous pour trouver une classe que je ne reconnais pas. La lisibilité est primordiale, et je conviens que le code ne devrait pas nécessiter un IDE pour le lire.
Le plus important est que l’importation de Java.awt.*
peut rendre votre programme incompatible avec une future version de Java:
Supposons que vous ayez une classe nommée "ABC", que vous utilisiez JDK 8 et que vous importiez Java.util.*
. Supposons maintenant que Java 9 soit sorti et qu’il ait une nouvelle classe dans le paquetage Java.util
qui, par coïncidence, s’appelle également "ABC". Votre programme maintenant ne compilera pas sur Java 9, car le compilateur ne sait pas si, avec le nom "ABC", vous voulez dire votre propre classe ou la nouvelle classe dans Java.awt
.
Vous n'aurez pas ce problème si vous importez uniquement les classes explicitement à partir de Java.awt
que vous utilisez réellement.
Ressources:
Il n'y a pas d'impact à l'exécution, car le compilateur remplace automatiquement * par des noms de classe concrets. Si vous décompilez le fichier .class, vous ne verrez jamais import ...*
.
C # always utilise * (implicitement) car vous ne pouvez que using
nom de package. Vous ne pouvez jamais spécifier le nom de la classe. Java introduit la fonctionnalité après c #. (Java est tellement compliqué à de nombreux égards, mais cela dépasse ce sujet).
Dans Intellij Idea, lorsque vous "organisez les importations", il remplace automatiquement plusieurs importations du même package par *. Il s'agit d'une fonctionnalité obligatoire car vous ne pouvez pas la désactiver (même si vous pouvez augmenter le seuil).
Le cas répertorié dans la réponse acceptée n'est pas valide. Sans * vous avez toujours le même problème. Vous devez spécifier le nom de pakcage dans votre code, que vous utilisiez * ou non.
Pour mémoire: Lorsque vous ajoutez une importation, vous indiquez également vos dépendances.
Vous pouvez voir rapidement quelles sont les dépendances des fichiers (à l'exclusion des classes du même espace de noms).