Java Pacotes e import
Um programa de verdade não cabe num arquivo só: ele tem dezenas, centenas de classes. Para não virar bagunça, o Java agrupa classes em pacotes, que são como pastas com nome. Nesta aula você vai criar um pequeno projeto com dois pacotes, compilar e rodar no terminal, e entender de uma vez o que são aquelas linhas import java.util.Scanner; que você copia desde o Nível 1.
- O que é um pacote e o "nome completo" de uma classe (
java.util.ArrayList). - Como declarar um pacote com
packagee como as pastas precisam acompanhar o nome. - Como compilar com
javac -d out …e rodar comjava -cp out br.com.ana.Main. - As formas de
import: uma classe,*,import staticeimport module. - O que fazer quando duas classes têm o mesmo nome (
reference to Date is ambiguous). - Por que
String,MatheSystemnunca precisaram deimport.
Esta aula usa o terminal. Se javac e java ainda são novidade, reveja javac e java. As sessões acontecem na máquina da Ana, na pasta ~/java.
A ideia: sobrenomes para classes
Na escola da Ana há duas alunas chamadas Maria. Para não confundir, a chamada usa o nome completo: Maria Silva e Maria Souza. Com classes acontece o mesmo. A biblioteca do Java tem duas classes chamadas Date: uma para datas em geral e outra para bancos de dados. Elas vivem em pacotes diferentes, e o nome do pacote funciona como sobrenome:
java.util.Date: a classeDatedo pacotejava.util.java.sql.Date: a classeDatedo pacotejava.sql.
Um pacote (em inglês, package) é um grupo de classes relacionadas, com um nome formado por partes separadas por ponto. O nome completo de uma classe (o fully qualified name, "nome totalmente qualificado") é o pacote + ponto + o nome da classe. E cada parte do pacote corresponde a uma pasta no disco: o pacote java.util é a pasta java/util.
Pacotes servem para três coisas:
- Organizar: classes do mesmo assunto ficam juntas (tudo de datas em
java.time, tudo de arquivos emjava.nio.file). - Evitar conflito de nomes: o seu
Produtonão briga com oProdutode outra empresa. - Controlar o acesso: uma classe pode ser visível só dentro do próprio pacote (você viu isso em Modificadores de Acesso; aqui vai ver o erro real).
Os programas que você fez até agora não tinham pacote?
Não tinham. Uma classe sem a linha package fica no pacote padrão (default package), um pacote sem nome. Para exercícios de um arquivo só, isso é ótimo, e o guia continua usando assim. Em qualquer projeto de verdade, toda classe fica num pacote com nome.
Como escolher o nome do pacote
A convenção do Java é usar o domínio da internet ao contrário, todo em minúsculas. Se a Ana tivesse o site ana.com.br, os pacotes dela começariam com br.com.ana. Como domínios são únicos no mundo, os nomes de pacotes também ficam únicos. Depois do domínio, vêm as partes do sistema:
| Pacote | O que guardaria |
|---|---|
br.com.ana | A classe principal, com o main |
br.com.ana.modelo | As classes de dados: Produto, Cliente |
br.com.ana.relatorio | Classes que geram relatórios |
org.junit.jupiter.api | Um exemplo real: a biblioteca de testes JUnit (site junit.org) |
Regras práticas: só letras minúsculas, números e ponto; nada de acento, espaço ou hífen; pacotes que começam com java. são reservados ao próprio Java: o javac até compila, mas a JVM se recusa a carregar a classe (java.lang.SecurityException: Prohibited package name: java.ana, "nome de pacote proibido"). Evite também javax., usado por bibliotecas oficiais.
Um projeto com dois pacotes
A Ana vai montar a loja dela com duas classes: Produto, no pacote br.com.ana.modelo, e Main, no pacote br.com.ana. O código-fonte fica numa pasta src (de source, "fonte"), e as pastas dentro dela seguem o nome dos pacotes:
$ cd java/loja $ find src src src/br src/br/com src/br/com/ana src/br/com/ana/modelo src/br/com/ana/modelo/Produto.java src/br/com/ana/Main.java
O find mostra tudo o que há dentro de src, pasta por pasta. Repare: o pacote br.com.ana.modelo virou o caminho br/com/ana/modelo. Agora, o conteúdo dos arquivos:
package br.com.ana.modelo;
public class Produto {
private String nome;
private double preco;
public Produto(String nome, double preco) {
this.nome = nome;
this.preco = preco;
}
public String getNome() {
return nome;
}
public double getPreco() {
return preco;
}
}
- package
- "Pacote": diz a que pacote esta classe pertence. Tem que ser a primeira linha de código do arquivo (antes só podem vir comentários).
- br.com.ana.modelo
- O nome do pacote. Deve combinar com a pasta onde o arquivo está.
- ;
- Termina a declaração, como qualquer comando Java.
- public class Produto
- O
publicaqui é essencial: sem ele, a classe só seria visível dentro do pacotebr.com.ana.modelo, e oMain, que está em outro pacote, não poderia usá-la.
package br.com.ana;
import br.com.ana.modelo.Produto;
public class Main {
public static void main(String[] args) {
Produto p = new Produto("Café", 18.90);
System.out.println(p.getNome() + ": R$ " + p.getPreco());
}
}
- package br.com.ana;
- O
Mainfica no pacotebr.com.ana, a pasta "de cima". - import
- "Importar": avisa que, neste arquivo,
Produtoquer dizerbr.com.ana.modelo.Produto. Vem depois dopackagee antes da classe. - br.com.ana.modelo.Produto
- O nome completo da classe importada.
Apesar das pastas, para o Java br.com.ana e br.com.ana.modelo são dois pacotes independentes. Estar "embaixo" não dá nenhum acesso especial: o Main precisa importar o Produto como importaria qualquer classe de fora.
Compilar com javac -d out
Com pacotes, a forma de compilar muda um pouco. A opção -d (de directory, "diretório") diz ao javac em que pasta colocar os arquivos .class. Ele cria lá dentro as pastas dos pacotes sozinho:
$ javac -d out src/br/com/ana/Main.java src/br/com/ana/modelo/Produto.java $ find out out out/br out/br/com out/br/com/ana out/br/com/ana/modelo out/br/com/ana/modelo/Produto.class out/br/com/ana/Main.class
- javac
- O compilador (veja javac e java).
- -d out
- Coloque os
.classna pastaout(de output, "saída"), criando a pasta se preciso. - src/br/com/ana/Main.java …
- Os arquivos a compilar, com o caminho a partir da pasta atual.
Os fontes (.java) ficam em src; os compilados (.class), em out, com a mesma árvore de pacotes. Separar as duas coisas é o padrão em todo projeto Java (o Maven usa target/classes no lugar de out; veja Maven).
Digitar todos os arquivos cansa. Há duas formas mais práticas:
$ javac -d out $(find src -name "*.java") « o find lista todos os .java $ javac -d out -sourcepath src src/br/com/ana/Main.java « o javac acha o resto sozinho
$(find src -name "*.java"): o Bash roda ofinde coloca a lista de arquivos no lugar. É um recurso do terminal, não do Java.-sourcepath src: diz aojavac"os fontes começam emsrc". Ao ver oimport br.com.ana.modelo.Produto, ele procurasrc/br/com/ana/modelo/Produto.javae compila também. É aqui que a regra "pasta = pacote" fica obrigatória: se o arquivo estiver em outra pasta, ojavacnão o encontra.
Rodar com java -cp out
Para rodar, você passa ao java duas informações: onde estão os .class e o nome completo da classe que tem o main.
$ java -cp out br.com.ana.Main Café: R$ 18.9
- java
- O lançador, que inicia a JVM.
- -cp out
- Classpath ("caminho das classes"): a pasta onde a JVM começa a procurar.
-cpé a abreviação de-classpath(as duas funcionam). - br.com.ana.Main
- O nome completo da classe, com pontos. A JVM converte em
out/br/com/ana/Main.class. Sem.classno fim.
O programa mostrou 18.9, e não 18.90: um double é impresso sem os zeros que não fazem diferença. Para mostrar dinheiro com duas casas, veja Formatar Texto.
Sem o -cp, a JVM procura na pasta atual. Por isso, de dentro de out, também funciona, com pontos ou com barras:
$ cd out $ java br.com.ana.Main Café: R$ 18.9 $ java br/com/ana/Main Café: R$ 18.9 $ cd ..
O que não funciona é usar só o nome curto, ou esquecer onde estão as classes. O lançador java responde em português:
$ java -cp out Main Erro: Não foi possível localizar nem carregar a classe principal Main Causada por: java.lang.ClassNotFoundException: Main
A classe se chama br.com.ana.Main; uma classe chamada só Main, no pacote padrão, não existe em out. ClassNotFoundException = "exceção de classe não encontrada".
Atalho: rodar direto o fonte
Java 22+ O modo "arquivo-fonte" (java Arquivo.java, que você usa desde javac e java) passou a entender pacotes e vários arquivos: ele descobre, pelo package, onde fica a raiz dos fontes e compila na memória as outras classes que o programa usa.
$ java src/br/com/ana/Main.java Café: R$ 18.9
Ótimo para testar. Mas nada é gravado em disco; para distribuir o programa você ainda compila com javac -d (e depois empacota num JAR). No JDK 21 ou anterior, esse comando só funciona com programas de um arquivo.
As formas de import
O import não "carrega" nada nem deixa o programa maior. Ele é só um atalho de nome: em vez de escrever o nome completo toda vez, você avisa uma vez no topo do arquivo. Prova disso: dá para não usar import nenhum e escrever os nomes completos:
public class Main {
public static void main(String[] args) {
java.util.List<String> frutas = java.util.List.of("maçã", "uva");
java.lang.String nome = "Ana";
java.lang.System.out.println(nome + " " + frutas);
System.out.println(java.time.LocalDate.of(2026, 10, 16).getDayOfWeek());
}
}
$ java Main.java Ana [maçã, uva] FRIDAY « 16/10/2026 é uma sexta-feira
Funciona, mas é cansativo de ler. Por isso existem os imports:
1. Uma classe: import pacote.Classe;
A forma mais comum, e a recomendada. Uma linha por classe:
import java.util.ArrayList; import java.util.Collections; import java.util.Scanner;
Lendo o topo do arquivo, você sabe exatamente de onde vem cada classe. Os editores (IntelliJ, VS Code) escrevem e organizam essas linhas para você.
2. O pacote inteiro: import pacote.*;
O asterisco (*, o "curinga") importa todas as classes de um pacote:
import java.util.*; // ArrayList, List, Scanner, Random, HashMap…
Duas coisas que o * não faz: ele não importa os "subpacotes" (import java.util.*; não traz java.util.function.Function, porque são pacotes independentes) e ele não deixa o programa mais lento (continua sendo só atalho de nome). A desvantagem é outra: fica difícil saber de onde vem cada classe, e aparecem conflitos de nome, como você vai ver logo abaixo.
3. Membros static: import static
Na aula static você viu que Math.sqrt e Math.PI são da classe Math. O import static traz esses membros para usar sem o nome da classe:
import static java.lang.Math.PI;
import static java.lang.Math.sqrt;
public class Main {
public static void main(String[] args) {
double raio = 2;
System.out.println(PI * raio * raio);
System.out.println(sqrt(144));
}
}
$ java Main.java 12.566370614359172 « a área do círculo de raio 2 12.0
Também existe import static java.lang.Math.*;, que traz todos os membros static de Math. Use com moderação: num código grande, um sqrt solto faz o leitor perguntar "de onde veio isso?". Onde ele brilha é nos testes: import static org.junit.jupiter.api.Assertions.*; (veja Testes com JUnit).
4. Um módulo inteiro: import module
Java 25+ Uma novidade do Java 25: import module java.base; importa de uma vez todos os pacotes públicos do módulo java.base, que contém java.util, java.time, java.io, java.nio.file, java.math e outros.
import module java.base;
public class Main {
public static void main(String[] args) {
List<String> frutas = new ArrayList<>(List.of("uva", "maçã"));
Collections.sort(frutas);
System.out.println(frutas + " " + LocalDate.of(2026, 10, 16));
}
}
$ java Main.java [maçã, uva] 2026-10-16
É prático em programas pequenos e scripts. Em projetos, os imports de uma classe continuam sendo o padrão. Módulos são assunto de Módulos (JPMS).
Missão: este programa não compila: o javac não sabe o que são ArrayList e Collections. Rode para ver os três erros cannot find symbol. Depois acrescente, no topo, os import que faltam (as duas classes estão no pacote java.util). A saída deve ser [Ana, Bruno, Carla], em ordem alfabética.
public class Main {
public static void main(String[] args) {
ArrayList<String> alunos = new ArrayList<>();
alunos.add("Carla");
alunos.add("Ana");
alunos.add("Bruno");
Collections.sort(alunos);
System.out.println(alunos);
}
}
import java.util.ArrayList;
import java.util.Collections;
public class Main {
public static void main(String[] args) {
ArrayList<String> alunos = new ArrayList<>();
alunos.add("Carla");
alunos.add("Ana");
alunos.add("Bruno");
Collections.sort(alunos);
System.out.println(alunos);
}
}
java.lang: o pacote que vem de graça
Se todo nome precisa de pacote, por que você nunca importou String, System, Math ou Integer? Porque elas moram no pacote java.lang (de language, "linguagem"), e o compilador acrescenta sozinho, em todo arquivo, um import java.lang.*; invisível. São as classes tão básicas que seria chato importá-las sempre.
Precisa de import? | Exemplos |
|---|---|
Não: pacote java.lang | String, System, Math, Integer, Double, Character, Object, StringBuilder, Thread, as exceções comuns |
| Não: o mesmo pacote da sua classe | As outras classes do seu pacote (no pacote padrão, as do mesmo arquivo ou da mesma pasta) |
| Sim: qualquer outro pacote | java.util.Scanner, java.util.ArrayList, java.time.LocalDate, java.math.BigDecimal |
Repare que java.lang vale só para o próprio pacote: java.lang.reflect.Method, por exemplo, precisa de import. Um mapa dos pacotes mais usados está na próxima aula, A Biblioteca Padrão.
Conflito de nomes
A Ana importou dois pacotes inteiros, e os dois têm uma classe Date:
import java.util.*;
import java.sql.*;
public class Main {
public static void main(String[] args) {
List<String> nomes = new ArrayList<>();
Date hoje = new Date();
}
}
$ javac Main.java
Main.java:7: error: reference to Date is ambiguous
Date hoje = new Date();
^
both class java.sql.Date in java.sql and class java.util.Date in java.util match
Main.java:7: error: reference to Date is ambiguous
Date hoje = new Date();
^
both class java.sql.Date in java.sql and class java.util.Date in java.util match
2 errors
Reference to Date is ambiguous = "a referência a Date é ambígua", e a linha de baixo explica: "tanto java.sql.Date quanto java.util.Date combinam". Repare que o List não deu problema: só existe um List nesses dois pacotes. Duas formas de resolver:
- Importe a classe pelo nome: um import de uma classe sempre vence o
*. Acrescentarimport java.util.Date;resolve. - Use o nome completo para a outra: quando o mesmo arquivo precisa das duas, uma fica com o import e a outra é escrita por extenso.
import java.util.*;
import java.sql.*;
import java.util.Date;
public class Main {
public static void main(String[] args) {
List<String> nomes = new ArrayList<>();
Date hoje = new Date(0);
java.sql.Date dia = java.sql.Date.valueOf("2026-10-16");
System.out.println(hoje.getClass().getName());
System.out.println(dia.getClass().getName() + " " + dia);
}
}
$ java Main.java java.util.Date « Date, sem pacote, agora é a de java.util java.sql.Date 2026-10-16 « a outra, pelo nome completo
O getClass().getName() mostra o nome completo da classe de um objeto (mais em A Classe Object). Não existe "import com apelido" em Java (import … as …, como em outras linguagens): o nome completo é a única saída.
Pacotes e visibilidade
Lembra do public obrigatório em public class Produto? Veja o que acontece sem ele:
$ javac -d out $(find src -name "*.java")
src/br/com/ana/Main.java:3: error: Produto is not public in br.com.ana.modelo; cannot be accessed from outside package
import br.com.ana.modelo.Produto;
^
src/br/com/ana/Main.java:7: error: Produto is not public in br.com.ana.modelo; cannot be accessed from outside package
Produto p = new Produto("Café", 18.90);
^
src/br/com/ana/Main.java:7: error: Produto is not public in br.com.ana.modelo; cannot be accessed from outside package
Produto p = new Produto("Café", 18.90);
^
3 errors
"Produto não é pública em br.com.ana.modelo; não pode ser acessada de fora do pacote." Uma classe (ou atributo, ou método) sem modificador de acesso tem acesso de pacote (package-private): só as classes do mesmo pacote a enxergam. A tabela completa está em Modificadores de Acesso; o que importa aqui é que, com pacotes, a diferença entre public e "nada" passa a valer de verdade.
public por arquivo
Um arquivo .java pode ter várias classes, mas só uma public, com o mesmo nome do arquivo. As outras ficam com acesso de pacote: servem de "ajudantes" daquele arquivo. Por isso os exemplos do guia escrevem class Aluno (sem public) embaixo de public class Main.
Quando dá errado
$ javac Main.java
Main.java:3: error: cannot find symbol
ArrayList<String> alunos = new ArrayList<>();
^
symbol: class ArrayList
location: class Main
Main.java:3: error: cannot find symbol
ArrayList<String> alunos = new ArrayList<>();
^
symbol: class ArrayList
location: class Main
Main.java:7: error: cannot find symbol
Collections.sort(alunos);
^
symbol: variable Collections
location: class Main
3 errors
O que aconteceu: a classe existe, mas está em outro pacote, e o arquivo não a importou. O symbol: class ArrayList diz o nome que o compilador não reconheceu.
Como resolver: acrescente import java.util.ArrayList;. Se não souber o pacote, procure na documentação (veja A Biblioteca Padrão) ou deixe o editor sugerir.
$ javac -d out src/br/com/ana/Main.java
src/br/com/ana/Main.java:3: error: package br.com.ana.modelo does not exist
import br.com.ana.modelo.Produto;
^
src/br/com/ana/Main.java:7: error: cannot find symbol
Produto p = new Produto("Café", 18.90);
^
symbol: class Produto
location: class Main
src/br/com/ana/Main.java:7: error: cannot find symbol
Produto p = new Produto("Café", 18.90);
^
symbol: class Produto
location: class Main
3 errors
O que aconteceu: o javac não achou nenhuma classe daquele pacote. Três causas comuns: (1) você compilou só o Main.java, sem o Produto.java e sem -sourcepath; (2) há um erro de digitação no import ou no package (modelos × modelo); (3) o arquivo está numa pasta que não combina com o pacote.
Como resolver: compile todos os arquivos juntos (javac -d out $(find src -name "*.java")) ou use -sourcepath src, e confira se a linha package e a pasta dizem a mesma coisa.
$ java br.com.ana.Main Erro: Não foi possível localizar nem carregar a classe principal br.com.ana.Main Causada por: java.lang.ClassNotFoundException: br.com.ana.Main
O que aconteceu: o nome está certo, mas a JVM procurou na pasta atual (loja), e os .class estão em out. A outra causa clássica é usar o nome curto (java -cp out Main).
Como resolver: java -cp out br.com.ana.Main: a pasta de onde começam os pacotes no -cp, o nome completo no fim.
O que aconteceu: dois import …*; trouxeram classes com o mesmo nome (java.util.Date e java.sql.Date, java.util.List e java.awt.List).
Como resolver: importe pelo nome a classe que você quer (import java.util.Date;) e, se precisar da outra, escreva o nome completo.
O que aconteceu: a classe (ou o construtor, ou o método) não tem public e está em outro pacote.
Como resolver: acrescente public no que precisa ser usado de fora, ou mova as duas classes para o mesmo pacote.
Referência
| Escrita | O que faz |
|---|---|
package br.com.ana.modelo; | Primeira linha: a classe pertence a esse pacote (pasta br/com/ana/modelo) |
import java.util.Scanner; | Atalho para uma classe |
import java.util.*; | Atalho para todas as classes do pacote (não os subpacotes) |
import static java.lang.Math.sqrt; | Usar um membro static sem o nome da classe |
import module java.base; Java 25+ | Todos os pacotes de um módulo |
java.util.List (no código) | Nome completo, sem import |
javac -d out arquivos… | Compila e grava os .class em out/, com as pastas dos pacotes |
javac -d out -sourcepath src src/…/Main.java | Compila o Main e as classes que ele usa |
java -cp out br.com.ana.Main | Roda a classe pelo nome completo, procurando em out |
java src/br/com/ana/Main.java Java 22+ | Roda direto dos fontes, com pacotes |
Exercícios
1. A primeira linha
Complete a primeira linha de uma classe que fica na pasta src/br/com/ana/relatorio:
2. Importar uma classe
Complete para poder usar LocalDate, do pacote java.time:
3. Rodar com pacote
Os .class estão em out, e a classe principal é Main, do pacote br.com.ana. Complete o comando:
4. Qual destas classes pode ser usada sem nenhum import?
5. O arquivo tem import java.util.*;. Ele pode usar java.util.function.Predicate só como Predicate?
6. O que o -d out faz em javac -d out …?
Missão final: o programa abaixo usa sqrt e PI sem o Math. na frente, e por isso não compila (rode e veja os cannot find symbol). Sem mexer no main, acrescente no topo os import static necessários (um para java.lang.Math.PI e outro para java.lang.Math.sqrt, ou um só com *). A saída deve ter 12.566370614359172 e 12.0.
public class Main {
public static void main(String[] args) {
double raio = 2;
System.out.println(PI * raio * raio);
System.out.println(sqrt(144));
}
}
import static java.lang.Math.PI;
import static java.lang.Math.sqrt;
public class Main {
public static void main(String[] args) {
double raio = 2;
System.out.println(PI * raio * raio);
System.out.println(sqrt(144));
}
}
Resumo
- Pacote = grupo de classes com nome (
br.com.ana.modelo), que vira pasta (br/com/ana/modelo). O nome completo de uma classe inclui o pacote. package …;é a primeira linha do arquivo. Por convenção, o nome começa com o domínio ao contrário e é todo em minúsculas.- Compile com
javac -d out …e rode comjava -cp out pacote.Classe. No Java 22+,java src/…/Main.javaroda direto. importé só atalho de nome. Prefira uma classe por linha;*não inclui subpacotes;import statictraz membrosstatic.- Dois imports com o mesmo nome de classe:
reference to … is ambiguous. Importe pelo nome ou use o nome completo. java.lang(String,Math,System…) é importado automaticamente.