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.

Você vai aprender
  • O que é um pacote e o "nome completo" de uma classe (java.util.ArrayList).
  • Como declarar um pacote com package e como as pastas precisam acompanhar o nome.
  • Como compilar com javac -d out … e rodar com java -cp out br.com.ana.Main.
  • As formas de import: uma classe, *, import static e import module.
  • O que fazer quando duas classes têm o mesmo nome (reference to Date is ambiguous).
  • Por que String, Math e System nunca precisaram de import.

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 classe Date do pacote java.util.
  • java.sql.Date: a classe Date do pacote java.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:

  1. Organizar: classes do mesmo assunto ficam juntas (tudo de datas em java.time, tudo de arquivos em java.nio.file).
  2. Evitar conflito de nomes: o seu Produto não briga com o Produto de outra empresa.
  3. 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:

PacoteO que guardaria
br.com.anaA classe principal, com o main
br.com.ana.modeloAs classes de dados: Produto, Cliente
br.com.ana.relatorioClasses que geram relatórios
org.junit.jupiter.apiUm 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 public aqui é essencial: sem ele, a classe só seria visível dentro do pacote br.com.ana.modelo, e o Main, 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 Main fica no pacote br.com.ana, a pasta "de cima".
import
"Importar": avisa que, neste arquivo, Produto quer dizer br.com.ana.modelo.Produto. Vem depois do package e antes da classe.
br.com.ana.modelo.Produto
O nome completo da classe importada.
Pacotes não são "um dentro do outro"

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 .class na pasta out (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 o find e coloca a lista de arquivos no lugar. É um recurso do terminal, não do Java.
  • -sourcepath src: diz ao javac "os fontes começam em src". Ao ver o import br.com.ana.modelo.Produto, ele procura src/br/com/ana/modelo/Produto.java e compila também. É aqui que a regra "pasta = pacote" fica obrigatória: se o arquivo estiver em outra pasta, o javac nã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 .class no 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.langString, System, Math, Integer, Double, Character, Object, StringBuilder, Thread, as exceções comuns
Não: o mesmo pacote da sua classeAs outras classes do seu pacote (no pacote padrão, as do mesmo arquivo ou da mesma pasta)
Sim: qualquer outro pacotejava.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:

Este código tem um erro de propósito
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:

  1. Importe a classe pelo nome: um import de uma classe sempre vence o *. Acrescentar import java.util.Date; resolve.
  2. 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.

Uma classe 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

"cannot find symbol … class ArrayList" (faltou o import)
$ 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.

"package … does not exist"
$ 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.

"Não foi possível localizar nem carregar a classe principal"
$ 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.

"reference to … is ambiguous"

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.

"… is not public in …; cannot be accessed from outside package"

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

EscritaO 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.javaCompila o Main e as classes que ele usa
java -cp out br.com.ana.MainRoda 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:

import

3. Rodar com pacote

Os .class estão em out, e a classe principal é Main, do pacote br.com.ana. Complete o comando:

java -cp out

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 com java -cp out pacote.Classe. No Java 22+, java src/…/Main.java roda direto.
  • import é só atalho de nome. Prefira uma classe por linha; * não inclui subpacotes; import static traz membros static.
  • 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.