sidunea - sentencias de importacion java
¿Por qué es malo usar un comodín con una declaración de importación Java? (13)
Es mucho más conveniente y limpio usar una sola declaración como
import java.awt.*;
que importar un montón de clases individuales
import java.awt.Panel;
import java.awt.Graphics;
import java.awt.Canvas;
...
¿Qué hay de malo con el uso de un comodín en la declaración de import
?
- Ayuda a identificar conflictos de nombre de clase: dos clases en paquetes diferentes que tienen el mismo nombre. Esto se puede enmascarar con la importación *.
- Hace que las dependencias sean explícitas, de modo que cualquier persona que tenga que leer su código más tarde sepa qué fue lo que quiso importar y qué no lo hizo.
- Puede hacer que algunas compilaciones sean más rápidas porque el compilador no tiene que buscar en todo el paquete para identificar las dependencias, aunque esto no suele ser un gran problema con los compiladores modernos.
- Los aspectos inconvenientes de las importaciones explícitas se minimizan con los IDE modernos. La mayoría de los IDE le permiten contraer la sección de importación por lo que no está en el camino, rellenar las importaciones automáticamente cuando sea necesario, e identificar automáticamente las importaciones no utilizadas para ayudar a limpiarlas.
La mayoría de los lugares en los que he trabajado que utilizan una cantidad significativa de Java hacen que las importaciones explícitas formen parte del estándar de codificación. A veces todavía uso * para crear prototipos rápidamente y luego amplío las listas de importación (algunos IDE también lo harán por usted) al producir el código.
Agrupa tu espacio de nombres, lo que requiere que especifiques completamente cualquier nombre de clase que sea ambiguo. La ocurrencia más común de esto es con:
import java.util.*;
import java.awt.*;
...
List blah; // Ambiguous, needs to be qualified.
También ayuda a concretar sus dependencias, ya que todas sus dependencias se enumeran en la parte superior del archivo.
Aquí hay un voto para las importaciones de estrellas. Una declaración de importación está destinada a importar un paquete , no una clase. Es mucho más limpio importar paquetes enteros; los problemas identificados aquí (p. ej., java.sql.Date
vs java.util.Date
) se solucionan fácilmente por otros medios, en realidad no se abordan mediante importaciones específicas y, por supuesto, no justifican importaciones increíblemente pedantes en todas las clases. No hay nada más desconcertante que abrir un archivo de origen y tener que pasar por 100 declaraciones de importación.
Hacer importaciones específicas dificulta la refactorización; Si elimina / renombra una clase, necesita eliminar todas sus importaciones específicas. Si cambia una implementación a una clase diferente en el mismo paquete, debe corregir las importaciones. Si bien estos pasos adicionales pueden ser automatizados, son realmente éxitos de productividad sin ganancias reales.
Incluso si Eclipse no hiciera importaciones de clase por defecto, todos seguirían haciendo importaciones de estrellas. Lo siento, pero realmente no hay una justificación racional para hacer importaciones específicas.
Aquí es cómo lidiar con los conflictos de clase:
import java.sql.*;
import java.util.*;
import java.sql.Date;
El único problema con esto es que desordena tu espacio de nombres local. Por ejemplo, supongamos que está escribiendo una aplicación Swing y, por lo tanto, necesita java.awt.Event
y también está interactuando con el sistema de calendario de la empresa, que tiene com.mycompany.calendar.Event
. Si importa ambos usando el método de comodín, ocurre una de estas tres cosas:
- Tienes un conflicto de nombres absoluto entre
java.awt.Event
ycom.mycompany.calendar.Event
, por lo que ni siquiera puedes compilar. - En realidad solo logras importar uno (solo uno de tus dos importados lo hace
.*
), Pero es incorrecto y te cuesta averiguar por qué tu código afirma que el tipo es incorrecto. - Cuando compilas tu código no hay
com.mycompany.calendar.Event
, pero cuando luego agregan uno, tu código previamente válido de repente deja de compilar.
La ventaja de enumerar explícitamente todas las importaciones es que puedo decir de un vistazo qué clase de equipo quería usar, lo que hace que la lectura del código sea mucho más fácil. Si solo está haciendo una cosa rápida, no hay nada explícitamente mal , pero los futuros mantenedores le agradecerán su claridad de lo contrario.
El más importante es que la importación de java.awt.*
Puede hacer que su programa sea incompatible con una futura versión de Java:
Supongamos que tiene una clase llamada "ABC", está utilizando JDK 8 e importa java.util.*
. Ahora, supongamos que Java 9 sale y tiene una nueva clase en el paquete java.util
que, por coincidencia, también se llama "ABC". Su programa ahora no se compilará en Java 9, porque el compilador no sabe si con el nombre "ABC" quiere decir su propia clase o la nueva clase en java.awt
.
No tendrá ese problema cuando importe solo esas clases explícitamente desde java.awt
que realmente usa.
Recursos:
En el libro de DDD
En cualquier tecnología de desarrollo en la que se basará la implementación, busque formas de minimizar el trabajo de refactorización de MÓDULOS. En Java, no se puede escapar de la importación a clases individuales, pero al menos puede importar paquetes completos a la vez, lo que refleja la intención de que los paquetes sean unidades altamente cohesivas y al mismo tiempo reduce el esfuerzo de cambiar los nombres de los paquetes.
Y si se desordena el espacio de nombres local, no es su culpa, culpe al tamaño del paquete.
En un proyecto anterior descubrí que el cambio de las importaciones de * a importaciones específicas reducía el tiempo de compilación a la mitad (de unos 10 minutos a unos 5 minutos). La importación * hace que el compilador busque en cada uno de los paquetes listados para una clase que coincida con la que usaste. Si bien este tiempo puede ser pequeño, se suma a proyectos grandes.
Un efecto secundario de la importancia de * era que los desarrolladores copiarían y pegarían líneas de importación comunes en lugar de pensar en lo que necesitaban.
Entre todos los puntos válidos hechos en ambos lados, no he encontrado mi razón principal para evitar el comodín: me gusta poder leer el código y saber directamente qué es cada clase, o si su definición no está en el idioma o El archivo, donde encontrarlo. Si se importa más de un paquete con *, debo buscar en cada uno de ellos para encontrar una clase que no reconozco. La legibilidad es suprema, y estoy de acuerdo en que el código no debe requerir un IDE para leerlo.
No es malo usar un comodín con una declaración de importación de Java.
En Clean Code , Robert C. Martin recomienda usarlos para evitar largas listas de importación.
Aquí está la recomendación:
J1: evitar listas de importación largas utilizando comodines
Si utiliza dos o más clases de un paquete, importe el paquete completo con
paquete de importación. *;
Las largas listas de importaciones son desalentadoras para el lector. No queremos saturar la parte superior de nuestros módulos con 80 líneas de importación. Más bien queremos que las importaciones sean una declaración concisa sobre con qué paquetes colaboramos.
Las importaciones específicas son dependencias difíciles, mientras que las importaciones de comodines no lo son. Si importas una clase específicamente, entonces esa clase debe existir. Pero si importa un paquete con un comodín, no es necesario que existan clases particulares. La declaración de importación simplemente agrega el paquete a la ruta de búsqueda al buscar nombres. Por lo tanto, tales importaciones no crean una verdadera dependencia y, por lo tanto, sirven para mantener nuestros módulos menos acoplados.
Hay momentos en que la larga lista de importaciones específicas puede ser útil. Por ejemplo, si está tratando con un código heredado y quiere saber para qué clases necesita construir simulacros y talones, puede recorrer la lista de importaciones específicas para averiguar los verdaderos nombres calificados de todas esas clases y luego poner los talones apropiados en su lugar. Sin embargo, este uso para importaciones específicas es muy raro. Además, la mayoría de los IDE modernos le permitirán convertir las importaciones con comodines a una lista de importaciones específicas con un solo comando. Así que incluso en el caso legado es mejor importar comodines.
Las importaciones de comodines a veces pueden causar conflictos de nombre y ambigüedades. Dos clases con el mismo nombre, pero en paquetes diferentes, deberán ser importadas específicamente, o al menos específicamente calificadas cuando se usan. Esto puede ser una molestia, pero es bastante raro que el uso de importaciones de comodines sea generalmente mejor que las importaciones específicas.
Por favor, vea mi artículo javadude.com/articles/importondemandisevil.html
En resumen, el mayor problema es que su código puede romperse cuando se agrega una clase a un paquete que importa. Por ejemplo:
import java.awt.*;
import java.util.*;
// ...
List list;
En Java 1.1, esto estaba bien; La lista se encontró en java.awt y no hubo conflicto.
Ahora, suponga que ingresa su código que funciona perfectamente, y un año más tarde, alguien más lo saca para editarlo y está utilizando Java 1.2.
Java 1.2 agregó una interfaz llamada Lista a java.util. ¡AUGE! Conflicto. El código perfectamente funcional ya no funciona.
Esta es una característica del lenguaje MAL . NO hay ninguna razón para que el código deje de compilar simplemente porque se agrega un tipo a un paquete ...
Además, hace que sea difícil para un lector determinar qué "Foo" estás usando.
Prefiero las importaciones específicas, porque me permite ver todas las referencias externas utilizadas en el archivo sin mirar todo el archivo. (Sí, sé que no necesariamente mostrará referencias completamente calificadas. Pero las evito siempre que sea posible).
Rendimiento : No hay impacto en el rendimiento, ya que el código de bytes es el mismo. aunque llevará a algunos gastos generales de compilación.
Compilación : en mi máquina personal, la compilación de una clase en blanco sin importar nada toma 100 ms, pero la misma clase al importar java. * Toma 170 ms.
No hay impacto de tiempo de ejecución, ya que el compilador reemplaza automáticamente el * con nombres de clase concretos. Si descompila el archivo .class, nunca verá
import ...*
.C # siempre usa * (implícitamente) ya que solo puedes
using
nombre del paquete. Nunca puedes especificar el nombre de la clase en absoluto. Java introduce la característica después de c #. (Java es tan complicado en muchos aspectos, pero está más allá de este tema).En Intellij Idea cuando "organiza importaciones", reemplaza automáticamente múltiples importaciones del mismo paquete con *. Esta es una característica obligatoria ya que no puede desactivarla (aunque puede aumentar el umbral).
El caso enumerado por la respuesta aceptada no es válido. Sin * todavía tienes el mismo problema. Debe especificar el nombre de pakcage en su código, sin importar que use * o no.