Pergunta

É muito mais conveniente e mais limpo usar uma única declaração como

import java.awt.*;

do que importar várias classes individuais

import java.awt.Panel;
import java.awt.Graphics;
import java.awt.Canvas;
...

O que há de errado em usar um curinga no import declaração?

Foi útil?

Solução

O único problema com isso é que ele se agrada ao seu espaço para nome local. Por exemplo, digamos que você está escrevendo um aplicativo de swing e, portanto, precisa java.awt.Event, e também estão interagindo com o sistema de calendário da empresa, que tem com.mycompany.calendar.Event. Se você importar ambos usando o método curinga, uma dessas três coisas acontece:

  1. Você tem um conflito totalmente nomeado entre java.awt.Event e com.mycompany.calendar.Event, e então você nem consegue compilar.
  2. Você realmente consegue importar apenas um (apenas uma de suas duas importações faz .*), mas é o errado, e você luta para descobrir por que seu código está reivindicando que o tipo está errado.
  3. Quando você compila seu código, não há com.mycompany.calendar.Event, mas quando eles mais tarde adicionam um, seu código anteriormente válido para de repente para de compilar.

A vantagem de listar explicitamente todas as importações é que eu posso dizer rapidamente qual classe você pretendia usar, o que simplesmente facilita a leitura do código. Se você está apenas fazendo uma coisa rápida, não há nada explicitamente errado, mas os futuros mantenedores agradecerão por sua clareza.

Outras dicas

Aqui está uma votação por importações de estrelas. Uma declaração de importação tem como objetivo importar um pacote, não uma aula. É muito mais limpo importar pacotes inteiros; os problemas identificados aqui (por exemplo java.sql.Date vs. java.util.Date) são facilmente remediados por outros meios, não verdade abordado por importações específicas e certamente não justifica importações insanamente pedantes em todas as classes. Não há nada mais desconcertante do que abrir um arquivo de origem e precisar de 100 instruções de importação.

Fazer importações específicas dificulta a refatoração; Se você remover/renomear uma classe, precisará remover tudo de suas importações específicas. Se você alternar uma implementação para uma classe diferente no mesmo pacote, precisará consertar as importações. Embora essas etapas extras possam ser automatizadas, elas são realmente hits de produtividade sem ganho real.

Mesmo que o Eclipse não tivesse as importações de classe por padrão, todos ainda estariam fazendo importações de estrelas. Sinto muito, mas realmente não há justificativa racional para fazer importações específicas.

Veja como lidar com conflitos de classe:

import java.sql.*;
import java.util.*;
import java.sql.Date;

Por favor, veja meu artigo Importar sob demanda é mau

Em resumo, o maior problema é que seu código pode quebrar quando uma aula é adicionado para um pacote que você importa. Por exemplo:

import java.awt.*;
import java.util.*;

// ...

List list;

No Java 1.1, isso foi bom; A lista foi encontrada em Java.awt e não houve conflito.

Agora, suponha que você verifique seu código perfeitamente funcionando e, um ano depois, alguém o traga para editá -lo e está usando o Java 1.2.

O Java 1.2 adicionou uma interface nomeada ao java.util. ESTRONDO! Conflito. O código perfeitamente funcional não funciona mais.

Isto é um MAL recurso de idioma. Há NÃO razão pela qual o código deve parar de compilar apenas porque um tipo é adicionado para um pacote ...

Além disso, torna difícil para um leitor determinar qual "foo" você está usando.

Isso é não é ruim usar um curinga com uma instrução de importação Java.

Em Código Limpo, Roberto C.Na verdade, Martin recomenda usá-los para evitar longas listas de importação.

Aqui está a recomendação:

J1:Evite longas listas de importação usando curingas

Se você usar duas ou mais classes de um pacote, importe todo o pacote com

pacote de importação.*;

As longas listas de importações são assustadoras para o leitor.Não queremos desordenar os topos de nossos módulos com 80 linhas de importações.Em vez disso, queremos que as importações sejam uma declaração concisa sobre quais pacotes colaboramos.

Importações específicas são dependências difíceis, enquanto as importações de curinga não são.Se você importar especificamente uma classe, essa classe deve existir.Mas se você importar um pacote com um curinga, nenhuma classes específicas precisará existir.A declaração de importação simplesmente adiciona o pacote ao caminho de pesquisa ao caçar nomes.Portanto, nenhuma dependência verdadeira é criada por essas importações e, portanto, elas servem para manter nossos módulos menos acoplados.

Há momentos em que a longa lista de importações específicas pode ser útil.Por exemplo, se você está lidando com o código herdado e deseja descobrir quais classes precisam para criar zombarias e stubs, pode caminhar pela lista de importações específicas para descobrir os nomes qualificados de todas essas classes e depois colocar os stubs apropriados no lugar.No entanto, esse uso para importações específicas é muito raro.Além disso, a maioria dos IDEs modernos permitirá que você converta as importações curinga em uma lista de importações específicas com um único comando.Portanto, mesmo no caso herdado, é melhor importar curingas.

Às vezes, as importações de curinga podem causar conflitos e ambiguidades.Duas classes com o mesmo nome, mas em pacotes diferentes, precisarão ser importadas especificamente, ou pelo menos especificamente qualificadas quando usadas.Isso pode ser um incômodo, mas é raro o suficiente para que o uso de importações de curinga ainda seja geralmente melhor que as importações específicas.

Isso desorganiza seu namespace, exigindo que você especifique completamente quaisquer nomes de classe que sejam ambíguos.A ocorrência mais comum disso é com:

import java.util.*;
import java.awt.*;

...
List blah; // Ambiguous, needs to be qualified.

Também ajuda a tornar suas dependências concretas, já que todas elas estão listadas no topo do arquivo.

Desempenho:Nenhum impacto no desempenho, pois o código de bytes é o mesmo.embora isso leve a algumas despesas gerais de compilação.

Compilação:na minha máquina pessoal, compilar uma classe em branco sem importar nada leva 100 ms, mas a mesma classe ao importar java.* leva 170 ms.

  1. Ajuda a identificar conflitos de nomes de classe:duas classes em pacotes diferentes que possuem o mesmo nome.Isso pode ser mascarado com a importação *.
  2. Ele torna as dependências explícitas, para que qualquer pessoa que precise ler seu código posteriormente saiba o que você pretendia importar e o que não pretendia importar.
  3. Ele pode tornar a compilação mais rápida porque o compilador não precisa pesquisar o pacote inteiro para identificar dependências, embora isso geralmente não seja um grande problema com os compiladores modernos.
  4. Os aspectos inconvenientes das importações explícitas são minimizados com IDEs modernos.A maioria dos IDEs permite recolher a seção de importação para que ela não atrapalhe, preencher automaticamente as importações quando necessário e identificar automaticamente as importações não utilizadas para ajudar a limpá-las.

A maioria dos lugares em que trabalhei que usam uma quantidade significativa de Java tornam as importações explícitas parte do padrão de codificação.Às vezes, ainda uso * para prototipagem rápida e, em seguida, expando as listas de importação (alguns IDEs também farão isso para você) ao produzir o código.

Prefiro importações específicas, pois me permitem ver todas as referências externas utilizadas no arquivo sem olhar o arquivo inteiro.(Sim, eu sei que não mostrará necessariamente referências totalmente qualificadas.Mas eu os evito sempre que possível.)

Em um projeto anterior, descobri que mudar de *-importações para importações específicas reduziu o tempo de compilação pela metade (de cerca de 10 minutos para cerca de 5 minutos).O *-import faz com que o compilador procure em cada um dos pacotes listados uma classe que corresponda àquela que você usou.Embora esse tempo possa ser pequeno, ele é útil para grandes projetos.

Um efeito colateral do *-import foi que os desenvolvedores copiariam e colariam linhas de importação comuns em vez de pensar no que precisavam.

Em Livro DDD

Em qualquer tecnologia de desenvolvimento em que a implementação seja baseada, procure maneiras de minimizar o trabalho de refatorar módulos.Em Java, não há escapar da importação para classes individuais, mas você pode pelo menos importar pacotes inteiros por vez, refletindo a intenção de que os pacotes são unidades altamente coesos e, simultaneamente, reduzem o esforço de alterar os nomes de pacotes.

E se isso sobrecarregar o namespace local, não é sua culpa - culpe o tamanho do pacote.

O mais importante é que a importação java.awt.* pode tornar seu programa incompatível com uma versão futura do Java:

Suponha que você tenha uma classe chamada "ABC", esteja usando JDK 8 e importe java.util.*.Agora, suponha que o Java 9 seja lançado e tenha uma nova classe no pacote java.util que por coincidência também é chamado de "ABC".Seu programa agora não será compilado em Java 9, porque o compilador não sabe se com o nome "ABC" você se refere à sua própria classe ou à nova classe em java.awt.

Você não terá esse problema ao importar apenas essas classes explicitamente do java.awt que você realmente usa.

Recursos:

Importações Java

Entre todos os pontos válidos apresentados por ambos os lados, não encontrei meu principal motivo para evitar o curinga:Gosto de poder ler o código e saber diretamente o que é cada classe, ou se sua definição não estiver na linguagem ou no arquivo, onde encontrá-la.Se mais de um pacote for importado com * eu tenho que pesquisar cada um deles para encontrar uma classe que não reconheço.A legibilidade é suprema e concordo que o código não deveria exigir um IDE para lê-lo.

  • Não há impacto no tempo de execução, pois o compilador substitui automaticamente * por nomes de classes concretos.Se você descompilar o arquivo .class, nunca verá import ...*.

  • C# sempre usa * (implicitamente) como você só pode using nome do pacote.Você nunca pode especificar o nome da classe.Java introduz o recurso após c#.(Java é muito complicado em muitos aspectos, mas está além deste tópico).

  • No Intellij Idea, quando você "organiza as importações", ele substitui automaticamente várias importações do mesmo pacote por *.Este é um recurso obrigatório, pois você não pode desligá-lo (embora possa aumentar o limite).

  • O caso listado pela resposta aceita não é válido.Sem * você ainda tem o mesmo problema.Você precisa especificar o nome do pacote em seu código, independentemente de usar * ou não.

Para registro:Ao adicionar uma importação, você também indica suas dependências.

Você pode ver rapidamente quais são as dependências dos arquivos (excluindo classes do mesmo namespace).

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top