Tópicos Especiais em Java
1. A classe Object e o tipo mais genérico de todos
Seção intitulada “1. A classe Object e o tipo mais genérico de todos”Em Java, todas as classes herdam direta ou indiretamente de java.lang.Object. Isso significa que qualquer objeto tem alguns métodos em comum, como:
toString()equals(Object o)hashCode()getClass()
1.1 toString()
Seção intitulada “1.1 toString()”Retorna uma representação textual do objeto. Por padrão, é algo como NomeDaClasse@hashCode.
Empregado emp = new Empregado("Ana", "Silva", 3000.0);System.out.println(emp.toString()); // saída padrão, pouco amigávelÉ comum sobrescrever toString() para facilitar debug e impressão de objetos:
public class Empregado { // ...atributos, construtor...
@Override public String toString() { return nome + " " + sobrenome + " - R$ " + salarioMensal; }}1.2 equals() e hashCode()
Seção intitulada “1.2 equals() e hashCode()”Usados para comparar objetos e para que coleções como HashSet e HashMap funcionem corretamente.
Empregado e1 = new Empregado("Ana", "Silva", 3000.0);Empregado e2 = new Empregado("Ana", "Silva", 3000.0);
System.out.println(e1 == e2); // false (endereços diferentes)System.out.println(e1.equals(e2)); // depende da implementação de equals()1.3 Object como tipo genérico
Seção intitulada “1.3 Object como tipo genérico”Como todas as classes herdam de Object, você pode ter estruturas de dados que guardam “qualquer coisa”:
Object[] vetor = new Object[3];vetor[0] = "Hello";vetor[1] = 123;vetor[2] = new Empregado("Ana", "Silva", 3000.0);No entanto, em código moderno, preferimos usar Generics (List<Empregado>, List<String>, etc.) para ter segurança de tipos em tempo de compilação.
2. Construtores
Seção intitulada “2. Construtores”Construtores são métodos especiais usados para criar e inicializar objetos. Eles têm o mesmo nome da classe e não possuem tipo de retorno.
2.1 Construtores coerentes com o domínio
Seção intitulada “2.1 Construtores coerentes com o domínio”Para classes de domínio (como Fatura, Data, Filme, Biocombustivel, Personagem), é comum:
- Ter um construtor que receba os atributos necessários.
- Validar dados dentro do construtor, se fizer sentido.
public class Data { private int dia; private int mes; private int ano;
public Data(int dia, int mes, int ano) { // Você pode chamar um método de validação aqui if (!validaData(dia, mes, ano)) { throw new IllegalArgumentException("Data inválida"); } this.dia = dia; this.mes = mes; this.ano = ano; }
// ...método validaData, getters, displayData()...}2.2 Construtores sobrecarregados
Seção intitulada “2.2 Construtores sobrecarregados”Você pode ter mais de um construtor, desde que as assinaturas sejam diferentes:
public class Biocombustivel { protected float quilogramas;
public Biocombustivel() { this.quilogramas = 1000f; // valor padrão }
public Biocombustivel(float quilogramas) { this.quilogramas = quilogramas; }}3. Collections (coleções)
Seção intitulada “3. Collections (coleções)”Collections são estruturas de dados prontas da biblioteca padrão para guardar múltiplos objetos de forma organizada.
As principais interfaces e implementações que você precisa conhecer para os exercícios:
List– lista ordenada, aceita duplicatas.Set– conjunto que não permite duplicatas.Map– pares chave-valor.- Implementações comuns:
ArrayList,LinkedList,HashSet,HashMap.
3.1 List e ArrayList
Seção intitulada “3.1 List e ArrayList”Uma List é similar a um “vetor dinâmico”: pode crescer e diminuir.
import java.util.ArrayList;import java.util.List;
List<Personagem> inimigos = new ArrayList<>();inimigos.add(new Personagem("Orc", 100, 10));inimigos.add(new Personagem("Goblin", 50, 5));inimigos.add(new Personagem("Lobo", 75, 15));Operações comuns:
for (Personagem inimigo : inimigos) { inimigo.atacar(jogador);}
Personagem primeiro = inimigos.get(0);int tamanho = inimigos.size();boolean listaVazia = inimigos.isEmpty();3.2 Set e HashSet (visão rápida)
Seção intitulada “3.2 Set e HashSet (visão rápida)”Um Set não aceita elementos duplicados. Útil, por exemplo, para garantir que assentos vendidos ("A1", "B3") não sejam repetidos.
import java.util.HashSet;import java.util.Set;
Set<String> assentosOcupados = new HashSet<>();assentosOcupados.add("A1"); // trueassentosOcupados.add("A1"); // false (já existe)3.3 Map e HashMap (visão rápida)
Seção intitulada “3.3 Map e HashMap (visão rápida)”Um Map armazena pares (chave, valor). Exemplo: nome da música como chave, objeto Musica como valor.
import java.util.HashMap;import java.util.Map;
Map<String, Musica> musicasDisponiveis = new HashMap<>();musicasDisponiveis.put("Hino do Real Paulista", new Musica("Hino do Real Paulista", "Banda X"));
Musica m = musicasDisponiveis.get("Hino do Real Paulista");if (m != null) { // música existe} else { // música não encontrada}Embora a lista peça apenas uma Collection, saber de Map ajuda em buscas mais eficientes.
4. Exceções em Java
Seção intitulada “4. Exceções em Java”Exceções representam erros ou situações anormais que podem ocorrer durante a execução do programa.
4.1 Tipos de exceções
Seção intitulada “4.1 Tipos de exceções”- Checked exceptions: precisam ser tratadas ou declaradas com
throwsem tempo de compilação (ex.:IOException,FileNotFoundException). - Unchecked exceptions: são subclasses de
RuntimeException. Não são obrigatórias de tratar (ex.:NullPointerException,ArithmeticException).
No contexto das listas, você vai:
- Criar exceções customizadas (como
GeradorCheioException). - Usar try-catch para tratar problemas de negócio (assento ocupado, idade insuficiente, música não encontrada, incompatibilidade de tipo de postagem).
4.2 Lançando exceções (throw)
Seção intitulada “4.2 Lançando exceções (throw)”Você pode lançar uma exceção explicitamente quando alguma regra é violada:
public double dividir(double dividendo, double divisor) { if (divisor == 0) { throw new ArithmeticException("Impossível dividir por zero!"); } return dividendo / divisor;}4.3 Tratando exceções (try-catch)
Seção intitulada “4.3 Tratando exceções (try-catch)”Para capturar e tratar uma exceção:
try { biogerador.carregar(biocombustivel);} catch (GeradorCheioException e) { System.out.println("O gerador está cheio. Processo interrompido.");}Exemplo de múltiplos casos de erro no cinema:
try { cinema.venderIngresso(cliente, nomeFilme, assento); System.out.println("Ingresso vendido com sucesso!");} catch (AssentoIndisponivelException e) { System.out.println("O ingresso não pode ser vendido pois seu assento não está mais disponível!");} catch (IdadeInsuficienteException e) { System.out.println("O ingresso não pode ser vendido pois sua idade não permite!");}4.4 Declarando exceções com throws
Seção intitulada “4.4 Declarando exceções com throws”Se um método pode lançar uma checked exception, você pode:
- Tratar internamente com
try-catch, ou - Propagar para quem chama usando
throws.
public void leArquivo(String caminho) throws FileNotFoundException { File file = new File(caminho); // ...código que pode lançar FileNotFoundException...}Em projetos maiores, é comum criar uma camada de serviço que lança exceções específicas, e uma camada de apresentação que trata e exibe mensagens amigáveis.
5. Exceções customizadas
Seção intitulada “5. Exceções customizadas”Você pode criar suas próprias classes de exceção, geralmente herdando de Exception (checked) ou RuntimeException (unchecked).
public class GeradorCheioException extends Exception { public GeradorCheioException(String mensagem) { super(mensagem); }}Uso:
public void carregar(Biocombustivel b) throws GeradorCheioException { if (this.cargaAtual >= this.cargaMaxima) { throw new GeradorCheioException("Biogerador já está cheio!"); } // ...restante do processamento...}Essas exceções deixam o código mais legível e a regra de negócio mais clara.