Java Core
Enums representam um conjunto fixo de constantes. São mais seguros que usar inteiros ou Strings soltas para representar estados e categorias.
public enum DiaSemana { SEGUNDA, TERCA, QUARTA, QUINTA, SEXTA, SABADO, DOMINGO}DiaSemana hoje = DiaSemana.SEXTA;
if (hoje == DiaSemana.SEXTA) { System.out.println("Quase fim de semana!");}Enums podem ter atributos e métodos:
public enum Planeta { MERCURIO(3.303e+23, 2.4397e6), VENUS(4.869e+24, 6.0518e6), TERRA(5.976e+24, 6.37814e6);
private final double massa; private final double raio;
Planeta(double massa, double raio) { this.massa = massa; this.raio = raio; }
public double massaEmKg() { return massa; }}Uso em switch:
switch (hoje) { case SABADO, DOMINGO -> System.out.println("Fim de semana"); default -> System.out.println("Dia útil");}Exceções
Seção intitulada “Exceções”Exceções representam situações anormais na execução do programa. Java usa um sistema hierárquico para classificá-las.
Hierarquia
Seção intitulada “Hierarquia”Throwable├── Error (erros da JVM - não tente capturar)└── Exception ├── RuntimeException (unchecked) │ ├── NullPointerException │ ├── ArrayIndexOutOfBoundsException │ ├── ClassCastException │ └── NumberFormatException └── IOException (checked) ├── FileNotFoundException └── ...Checked exceptions devem ser declaradas ou tratadas obrigatoriamente. Unchecked exceptions (subclasses de RuntimeException) são opcionais.
try / catch / finally
Seção intitulada “try / catch / finally”try { int resultado = 10 / 0;} catch (ArithmeticException e) { System.out.println("Erro: " + e.getMessage());} finally { System.out.println("Sempre executado, com ou sem erro");}Múltiplos catch:
try { String texto = null; System.out.println(texto.length());} catch (NullPointerException e) { System.out.println("Referência nula: " + e.getMessage());} catch (Exception e) { System.out.println("Erro genérico: " + e.getMessage());}Captura múltipla (Java 7+):
catch (IOException | SQLException e) { System.out.println("Erro de I/O ou banco: " + e.getMessage());}throw e throws
Seção intitulada “throw e throws”throw lança uma exceção manualmente. throws declara que um método pode lançar uma checked exception:
public double dividir(double a, double b) throws IllegalArgumentException { if (b == 0) { throw new IllegalArgumentException("Divisor não pode ser zero"); } return a / b;}Exceções customizadas
Seção intitulada “Exceções customizadas”public class SaldoInsuficienteException extends RuntimeException { private final double saldoAtual;
public SaldoInsuficienteException(double saldoAtual) { super("Saldo insuficiente. Saldo atual: " + saldoAtual); this.saldoAtual = saldoAtual; }
public double getSaldoAtual() { return saldoAtual; }}public void sacar(double valor) { if (valor > saldo) { throw new SaldoInsuficienteException(saldo); } saldo -= valor;}try-with-resources
Seção intitulada “try-with-resources”Recursos que implementam AutoCloseable são fechados automaticamente:
try (var reader = new BufferedReader(new FileReader("arquivo.txt"))) { String linha; while ((linha = reader.readLine()) != null) { System.out.println(linha); }} catch (IOException e) { e.printStackTrace();}Equivale a chamar reader.close() no finally, mas sem o código repetitivo.
Autoboxing e Unboxing
Seção intitulada “Autoboxing e Unboxing”Java converte automaticamente entre tipos primitivos e seus wrappers (Integer, Double, Boolean, etc.):
// Autoboxing: primitivo -> wrapperInteger obj = 42;List<Integer> lista = new ArrayList<>();lista.add(10); // int vira Integer automaticamente
// Unboxing: wrapper -> primitivoint valor = obj;int soma = lista.get(0) + 5;Cuidado com null: unboxing de um wrapper null lança NullPointerException:
Integer numero = null;int resultado = numero; // NullPointerException em runtime!Upcasting e Downcasting
Seção intitulada “Upcasting e Downcasting”Upcasting
Seção intitulada “Upcasting”Conversão de subclasse para superclasse - sempre segura e implícita:
Animal animal = new Cachorro(); // upcasting implícitoanimal.emitirSom();Downcasting
Seção intitulada “Downcasting”Conversão de superclasse para subclasse - requer cast explícito e pode lançar ClassCastException:
Animal animal = new Cachorro();
if (animal instanceof Cachorro) { Cachorro cachorro = (Cachorro) animal; // downcasting cachorro.buscarBola();}A partir do Java 16, instanceof com pattern matching elimina o cast manual:
if (animal instanceof Cachorro cachorro) { cachorro.buscarBola(); // cachorro já está tipado como Cachorro}Collections
Seção intitulada “Collections”O framework Collections oferece estruturas de dados prontas para uso. A interface raiz é Collection, com três subtipos principais.
Sequência ordenada que permite duplicatas. A implementação mais usada é ArrayList:
import java.util.ArrayList;import java.util.List;
List<String> nomes = new ArrayList<>();nomes.add("Ana");nomes.add("Bruno");nomes.add("Carlos");
System.out.println(nomes.get(0)); // "Ana"System.out.println(nomes.size()); // 3
nomes.remove("Bruno");System.out.println(nomes); // [Ana, Carlos]LinkedList é preferível quando há muitas inserções/remoções no meio da lista.
Não permite duplicatas e não garante ordem. Implementações:
import java.util.HashSet;import java.util.LinkedHashSet;import java.util.TreeSet;
Set<String> conjunto = new HashSet<>(); // sem ordem garantidaSet<String> ordenado = new LinkedHashSet<>(); // mantém ordem de inserçãoSet<String> arvore = new TreeSet<>(); // ordem natural (alfabética)
conjunto.add("banana");conjunto.add("maçã");conjunto.add("banana"); // ignorado, já existeSystem.out.println(conjunto.size()); // 2Mapeamento de chave para valor. Não permite chaves duplicadas:
import java.util.HashMap;import java.util.Map;
Map<String, Integer> idades = new HashMap<>();idades.put("Ana", 28);idades.put("Bruno", 32);idades.put("Carlos", 25);
System.out.println(idades.get("Ana")); // 28
// Iterar sobre entradasfor (Map.Entry<String, Integer> entrada : idades.entrySet()) { System.out.println(entrada.getKey() + ": " + entrada.getValue());}
// getOrDefault para valores ausentesint idadeDesconhecida = idades.getOrDefault("Daniela", -1);LinkedHashMap mantém ordem de inserção. TreeMap ordena pelas chaves.
Métodos utilitários
Seção intitulada “Métodos utilitários”import java.util.Collections;
List<Integer> numeros = new ArrayList<>(List.of(3, 1, 4, 1, 5, 9, 2, 6));
Collections.sort(numeros); // ordenaCollections.reverse(numeros); // inverteCollections.shuffle(numeros); // embaralhaint max = Collections.max(numeros);int min = Collections.min(numeros);Generics
Seção intitulada “Generics”Generics permitem criar classes, interfaces e métodos parametrizados por tipo, garantindo segurança em tempo de compilação.
Classes genéricas
Seção intitulada “Classes genéricas”public class Caixa<T> { private T conteudo;
public void guardar(T conteudo) { this.conteudo = conteudo; }
public T abrir() { return conteudo; }}
// UsoCaixa<String> caixaTexto = new Caixa<>();caixaTexto.guardar("Olá");String texto = caixaTexto.abrir();
Caixa<Integer> caixaNumero = new Caixa<>();caixaNumero.guardar(42);Métodos genéricos
Seção intitulada “Métodos genéricos”public static <T extends Comparable<T>> T maior(T a, T b) { return a.compareTo(b) >= 0 ? a : b;}
// Funciona com qualquer tipo comparávelSystem.out.println(maior(10, 20)); // 20System.out.println(maior("abc", "xyz")); // xyzWildcards
Seção intitulada “Wildcards”? representa um tipo desconhecido. Útil para métodos que trabalham com coleções de diferentes tipos:
// Aceita List<Integer>, List<Double>, List<Number>...public double somarLista(List<? extends Number> lista) { double soma = 0; for (Number n : lista) { soma += n.doubleValue(); } return soma;}Classe Object
Seção intitulada “Classe Object”Toda classe em Java herda de Object. Três métodos que frequentemente se sobrescreve:
toString()
Seção intitulada “toString()”Retorna uma representação em String do objeto. Chamado implicitamente em concatenação:
public class Produto { private String nome; private double preco;
@Override public String toString() { return nome + " - R$ " + String.format("%.2f", preco); }}
Produto p = new Produto("Caneta", 2.50);System.out.println(p); // "Caneta - R$ 2,50"equals() e hashCode()
Seção intitulada “equals() e hashCode()”Por padrão, equals() compara referências de memória. Para comparar conteúdo, sobrescreva:
public class Ponto { private int x; private int y;
@Override public boolean equals(Object obj) { if (this == obj) return true; if (!(obj instanceof Ponto outro)) return false; return this.x == outro.x && this.y == outro.y; }
@Override public int hashCode() { return Objects.hash(x, y); }}Regra: sempre que sobrescrever equals(), sobrescreva hashCode() também. Objetos iguais devem ter o mesmo hash.
Strings em Profundidade
Seção intitulada “Strings em Profundidade”Imutabilidade
Seção intitulada “Imutabilidade”Strings em Java são imutáveis - toda operação cria um novo objeto:
String a = "Java";String b = a.toUpperCase(); // "JAVA" - novo objeto// a ainda é "Java"Métodos principais
Seção intitulada “Métodos principais”String texto = " Olá, Mundo! ";
texto.trim() // "Olá, Mundo!" - remove espaços nas bordastexto.strip() // igual ao trim(), mas suporta Unicodetexto.length() // 15texto.toUpperCase() // " OLÁ, MUNDO! "texto.toLowerCase() // " olá, mundo! "texto.contains("Mundo") // truetexto.startsWith(" Olá") // truetexto.endsWith("! ") // truetexto.replace("Mundo", "Java") // " Olá, Java! "texto.substring(2, 6) // "Olá,"texto.split(",") // [" Olá", " Mundo! "]texto.indexOf("M") // 7String.valueOf(42) // "42"Integer.parseInt("123") // 123StringBuilder
Seção intitulada “StringBuilder”Para concatenações em loop, use StringBuilder - é mutável e muito mais eficiente:
StringBuilder sb = new StringBuilder();for (int i = 1; i <= 100; i++) { sb.append(i); if (i < 100) sb.append(", ");}String resultado = sb.toString();Manipulação de Arquivos
Seção intitulada “Manipulação de Arquivos”Leitura
Seção intitulada “Leitura”import java.io.BufferedReader;import java.io.FileReader;import java.io.IOException;
try (var reader = new BufferedReader(new FileReader("dados.txt"))) { String linha; while ((linha = reader.readLine()) != null) { System.out.println(linha); }} catch (IOException e) { System.err.println("Erro ao ler arquivo: " + e.getMessage());}Escrita
Seção intitulada “Escrita”import java.io.BufferedWriter;import java.io.FileWriter;import java.io.IOException;
try (var writer = new BufferedWriter(new FileWriter("saida.txt"))) { writer.write("Primeira linha"); writer.newLine(); writer.write("Segunda linha");} catch (IOException e) { System.err.println("Erro ao escrever arquivo: " + e.getMessage());}java.nio.file (moderno)
Seção intitulada “java.nio.file (moderno)”import java.nio.file.Files;import java.nio.file.Path;
Path caminho = Path.of("dados.txt");
// Ler todas as linhas de uma vezList<String> linhas = Files.readAllLines(caminho);
// Escrever todas as linhas de uma vezFiles.writeString(caminho, "conteúdo do arquivo");
// Verificar existênciaboolean existe = Files.exists(caminho);