Declaração Import

Pessoal, bom dia.

A declaração import doJava corresponde à declaração include do C/C++ ou à cláusula uses do Pascal. Sua finalidade é importar os recursos disponíveis na API do JDK e que sejam necessários no arquivo atual. Todos sabemos disso!

A minha pergunta é: o compilador não poderia simplesmente identificar o seu código e realizar a compilação sem a necessidade do import? Ou seja, ele saberia o que o código contém e buscaria a API necessária para a sua compilação?

De uma certa maneira isso já existe na no pacote java.lang. As classes String e System, por exemplo funcionam sendo que nunca precisamos dar um import nessas classes. Isso ocorre porque elas estão dentro do pacote java.lang, que é automaticamente importado para você. É o único pacote com esta característica. Talvez não tenhamos uma resposta para isso, mas não seria mais fácil para o programador se todos os pacotes, inclusive os que o próprio programador criasse, ter essa característica?

Forte abraço. Obrigado.

Bom dia.

A resposta é não.
A cada import utilizado, o código fica mais pesado na JVM, pois esta precisa “conhecer” mais classes.
Sem contar que vc pode criar classes com o mesmo nome de outras já existentes mas em pacotes diferentes.
Como o compilador poderia distinguir com facilidade?

1 curtida

Eu não consegui entender que você quis dizer. De boa! E parece que você concorda comigo, vamos lá:

“A cada import utilizado, o código fica mais pesado na JVM, pois esta precisa “conhecer” mais classes”

Então, faz jus a minha pergunta. Se quanto mais import eu tiver, mais trabalho eu dou para a JVM. Eu acho que você quis dizer que quanto mais import, menos trabalho pra JVM em pesquisar a enorme quantidade de API.

“Sem contar que vc pode criar classes com o mesmo nome de outras já existentes mas em pacotes diferentes.”

Bom, isso o compilador já faz quando utilizamos “palavras-reservadas”, qual seria a diferença se criássemos classes com o mesmo nome sem perceber?

Na verdade, eu só estou querendo entender a ciência da coisa, o motivo real de explicitar o pacote.

Explicitar as classes/pacotes a serem importadas tem vantagens:

  • otimizar recursos: sim, como você entendeu, isso evita que o java carregue classes que não serão usadas (economizando RAM), e facilita a busca por classes;

  • evita conflitos: imagine que você cria uma biblioteca para fazer parse de xml, e a chama de XMLParser. Daí outro programador cria uma biblioteca para a mesma coisa e com o mesmo nome. Se eu faço:

XMLParser parser = new XMLParser();

Como o compilador fará para saber se é para instanciar a sua classe ou a do outro programador? Sem que isso seja dito explicitamente, o compilador não tem como inferir qual o tipo a ser instanciado.

Abraço.

2 curtidas

A verdade é que vc NÃO PRECISA usar import se não quiser. Considere:

import java.util.List;
import java.util.ArrayList;
import java.time.LocalTime;

class Teste {
    public static void main(String[] args) {
        List<LocalTime> localTimes = new ArrayList<>();
        localTimes.add( LocalTime.now() );
    }
}

O código acima poderia ser reescrito sem imports:

class Teste {
    public static void main(String[] args) {
        java.util.List<java.time.LocalTime> localTimes =
                new java.util.ArrayList<>();
        localTimes.add( java.time.LocalTime.now() );
    }
}

Talvez vc esteja pensando neles como um requerimento que deveria ser desnecessário sendo que, na verdade, é uma facilidade muito bem vinda.

Acho que todos concordamos que pacotes (ou equivalentes em outras linguagens) são um recurso essencial, né? Eles nos permitem organizar melhor nosso código, evitam conflitos de nomes e, no caso do Java, ainda nos auxiliam nas nossas estratégias de encapsulamento (uma vez que nos permitem definir entidades que só são visiveis de dentro daquele pacote).

Pois bem, só que eles vão um pouco além disso. Todas as entidades declaradas em nosso programa (com algumas exceções) tem o que a especificação define como Simple Name e um Full Qualified Name.

O Simple Name é o nome usado para se referir a uma certa entidade de dentro do escopo na qual ela foi declarada.

O Full Qualified Name é usado para se referir a uma certa entidade de fora do contexto onde ela foi declarada.

E o pacote onde uma entidade foi declarada faz parte deste Full Qualified Name.

O que o import faz é nos permitir usar uma entidade qualquer fora do escopo de declaração dela a partir de seu Simple Name.

O compilador (e talvez até a JVM) poderia inferir qual entidade querermos usar com base no nosso código? Poderia.

Considere:

package um;

public class Teste {
    public void fazAlgumaCoisa() {}
}

E

package dois;

public class Teste {
    public void fazOutraCoisa() {}
}

E

package tres;

public class Programa {
    public static void main(String[] args) {
        Teste teste = new Teste();
        teste.fazAlgumaCoisa();
    }
}

Tenho duas classes com nome igual, mas em pacotes diferentes e o compilador poderia muito bem dizer que o Teste que quero é o que está dentro do pacote um, já que é o único que possui um método chamado fazAlgumaCoisa.

Porém, será que é mesmo o único? Será que meu classpath não possui mais nenhuma outra biblioteca que tenha uma classe com este nome e com um método igual? Vc poderia afirmar isso com toda certeza do mundo?

Eu particularmente só poderia afirmar isso se eu conhecesse muito bem cada biblioteca, cada framework e cada ferramenta instalada no meu computador (o que já seria mais trabalhoso ou chato ou inconveniente do que usar imports).

Mesmo assim eu ainda não seria capaz de dizer o mesmo do computador do meu cliente, ou dos meus clientes. Se meu programa vai rodar só na minha máquina, funcionaria bem, mas em geral programas serão distribuidos por ai.

Deixar que o compilador infira o tipo da entidade que queremos traria mais problemas e preocupações do que fazer o programador usar o Full Qualified Name ou alguns imports.

Fonte: https://docs.oracle.com/javase/specs/jls/se8/html/jls-6.html

2 curtidas

Não é igual não.
No C/C++ e Pascal o include e uses implica que o bytecode dos arquivos/units importados é incluído no executável resultante da compilação, tanto que se você fizer include/uses desnecessário, o seu executável ficará muito maior.

1 curtida

Entendi… não tinha percebido isso! E no Java se eu fizer imports desnecessários, meu arquivo fica maior?

Seu .class não ficará maior pois a lista de imports não faz parte do bytecode gerado, veja a especificação.
O import só é utilizado durante a compilação para o compilador encontrar a origem dos tipos (classes, interfaces e enums) referenciados no fonte.

1 curtida