Partilhar: WhatsApp
aulify
UC UC00619 · T. Desenv. Software

Ficha 02 · Java avançado

Excepções, ficheiros, JDBC, testes
Versão · Aluno
Tempo · 45 minutos
Aluno(a)
Turma
Data

Exercício 1 · Excepção custom

Cria uma excepção IdadeInvalidaException extends Exception. Modifica o setIdade de uma classe Pessoa para lançar esta excepção se a idade for negativa ou > 150. Demonstra try-catch.

Resposta:
class IdadeInvalidaException extends Exception {
    public IdadeInvalidaException(String message) {
        super(message);
    }
}

class Pessoa {
    private String nome;
    private int idade;

    public Pessoa(String nome) { this.nome = nome; }

    public void setIdade(int idade) throws IdadeInvalidaException {
        if (idade < 0 || idade > 150) {
            throw new IdadeInvalidaException("Idade inválida: " + idade);
        }
        this.idade = idade;
    }

    public int getIdade() { return idade; }
    public String getNome() { return nome; }
}

public class TestIdade {
    public static void main(String[] args) {
        Pessoa p = new Pessoa("Ana");

        try {
            p.setIdade(25);
            System.out.println("OK: " + p.getIdade());
            p.setIdade(-5);  // lança
        } catch (IdadeInvalidaException e) {
            System.out.println("Erro: " + e.getMessage());
        }
    }
}

Exercício 2 · Ler e processar ficheiro

Cria um ficheiro numeros.txt com 10 números (um por linha). Lê o ficheiro, calcula soma, média e máximo.

Resposta:
import java.nio.file.*;
import java.io.IOException;
import java.util.List;

public class ProcessaNumeros {
    public static void main(String[] args) throws IOException {
        List<String> linhas = Files.readAllLines(Path.of("numeros.txt"));

        int soma = 0;
        int maximo = Integer.MIN_VALUE;

        for (String linha : linhas) {
            int n = Integer.parseInt(linha.trim());
            soma += n;
            if (n > maximo) maximo = n;
        }

        double media = (double) soma / linhas.size();

        System.out.println("Soma: " + soma);
        System.out.println("Média: " + media);
        System.out.println("Máximo: " + maximo);

        // Versão com streams
        int[] valores = linhas.stream()
            .mapToInt(s -> Integer.parseInt(s.trim()))
            .toArray();

        int somaS = java.util.stream.IntStream.of(valores).sum();
        double mediaS = java.util.stream.IntStream.of(valores).average().orElse(0);
        int maxS = java.util.stream.IntStream.of(valores).max().orElse(0);
    }
}

Exercício 3 · Escrever log

Cria uma classe Logger com método log(String msg) que adiciona uma linha ao ficheiro app.log no formato [timestamp] msg. Usa Files.writeString com APPEND.

Resposta:
import java.nio.file.*;
import java.io.IOException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

public class Logger {
    private static final Path LOG_FILE = Path.of("app.log");
    private static final DateTimeFormatter FMT = 
        DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

    public static void log(String msg) {
        String linha = "[" + LocalDateTime.now().format(FMT) + "] " + msg + "\n";
        try {
            Files.writeString(LOG_FILE, linha, 
                StandardOpenOption.CREATE, 
                StandardOpenOption.APPEND);
        } catch (IOException e) {
            System.err.println("Erro ao escrever log: " + e.getMessage());
        }
    }

    public static void main(String[] args) {
        log("Aplicação iniciada");
        log("User logged in: ana@example.com");
        log("Database query took 230ms");
        log("Aplicação terminada");
    }
}

Exercício 4 · Streams — produtos

Dado este array:

List<Produto> produtos = List.of(
    new Produto("Caneta", 1.50),
    new Produto("Caderno", 5.00),
    new Produto("Lapis", 0.50),
    new Produto("Mochila", 35.00),
    new Produto("Estojo", 8.00)
);

Usa streams para: - Filtrar produtos com preço > 5€. - Imprimir os nomes em maiúsculas. - Calcular o preço total de todos os produtos.

Resposta:
import java.util.List;
import java.util.stream.Collectors;

record Produto(String nome, double preco) {}

public class StreamProdutos {
    public static void main(String[] args) {
        List<Produto> produtos = List.of(
            new Produto("Caneta", 1.50),
            new Produto("Caderno", 5.00),
            new Produto("Lapis", 0.50),
            new Produto("Mochila", 35.00),
            new Produto("Estojo", 8.00)
        );

        // Filtrar > 5€ e imprimir nomes em maiúsculas
        produtos.stream()
            .filter(p -> p.preco() > 5)
            .map(p -> p.nome().toUpperCase())
            .forEach(System.out::println);

        // Total
        double total = produtos.stream()
            .mapToDouble(Produto::preco)
            .sum();
        System.out.printf("Total: %.2f€%n", total);

        // Bonus: nomes ordenados por preço
        List<String> ordenados = produtos.stream()
            .sorted((a, b) -> Double.compare(b.preco(), a.preco()))
            .map(Produto::nome)
            .collect(Collectors.toList());
        System.out.println(ordenados);
    }
}

Exercício 5 · JDBC — conectar a SQLite

Cria um projecto Maven com SQLite (org.xerial:sqlite-jdbc). Conecta à BD loja.db, cria tabela produtos (id INTEGER PRIMARY KEY, nome TEXT, preco REAL), e insere 3 produtos.

Resposta:

pom.xml:

<dependency>
    <groupId>org.xerial</groupId>
    <artifactId>sqlite-jdbc</artifactId>
    <version>3.45.1.0</version>
</dependency>
import java.sql.*;

public class CriarBD {
    public static void main(String[] args) throws SQLException {
        String url = "jdbc:sqlite:loja.db";

        try (Connection conn = DriverManager.getConnection(url);
             Statement st = conn.createStatement()) {

            // Criar tabela
            st.execute("""
                CREATE TABLE IF NOT EXISTS produtos (
                    id INTEGER PRIMARY KEY AUTOINCREMENT,
                    nome TEXT NOT NULL,
                    preco REAL NOT NULL
                )
                """);

            // Inserir
            String sql = "INSERT INTO produtos (nome, preco) VALUES (?, ?)";
            try (PreparedStatement ps = conn.prepareStatement(sql)) {
                ps.setString(1, "Caneta");
                ps.setDouble(2, 1.50);
                ps.executeUpdate();

                ps.setString(1, "Caderno");
                ps.setDouble(2, 5.00);
                ps.executeUpdate();

                ps.setString(1, "Mochila");
                ps.setDouble(2, 35.00);
                ps.executeUpdate();
            }

            System.out.println("BD criada e populada!");
        }
    }
}

Exercício 6 · JDBC — DAO completo

Cria a classe ProdutoDAO com métodos listar(), inserir(Produto), actualizar(Produto), apagar(int id) para a BD do exercício 5.

Resposta:
import java.sql.*;
import java.util.*;

record Produto(int id, String nome, double preco) {}

public class ProdutoDAO {
    private final String url = "jdbc:sqlite:loja.db";

    public List<Produto> listar() throws SQLException {
        List<Produto> lista = new ArrayList<>();
        String sql = "SELECT id, nome, preco FROM produtos";

        try (Connection conn = DriverManager.getConnection(url);
             PreparedStatement ps = conn.prepareStatement(sql);
             ResultSet rs = ps.executeQuery()) {

            while (rs.next()) {
                lista.add(new Produto(
                    rs.getInt("id"),
                    rs.getString("nome"),
                    rs.getDouble("preco")
                ));
            }
        }
        return lista;
    }

    public void inserir(Produto p) throws SQLException {
        String sql = "INSERT INTO produtos (nome, preco) VALUES (?, ?)";
        try (Connection conn = DriverManager.getConnection(url);
             PreparedStatement ps = conn.prepareStatement(sql)) {
            ps.setString(1, p.nome());
            ps.setDouble(2, p.preco());
            ps.executeUpdate();
        }
    }

    public void actualizar(Produto p) throws SQLException {
        String sql = "UPDATE produtos SET nome = ?, preco = ? WHERE id = ?";
        try (Connection conn = DriverManager.getConnection(url);
             PreparedStatement ps = conn.prepareStatement(sql)) {
            ps.setString(1, p.nome());
            ps.setDouble(2, p.preco());
            ps.setInt(3, p.id());
            ps.executeUpdate();
        }
    }

    public void apagar(int id) throws SQLException {
        String sql = "DELETE FROM produtos WHERE id = ?";
        try (Connection conn = DriverManager.getConnection(url);
             PreparedStatement ps = conn.prepareStatement(sql)) {
            ps.setInt(1, id);
            ps.executeUpdate();
        }
    }

    public static void main(String[] args) throws SQLException {
        ProdutoDAO dao = new ProdutoDAO();

        // Listar
        dao.listar().forEach(System.out::println);

        // Inserir
        dao.inserir(new Produto(0, "Borracha", 0.80));

        // Apagar id=1
        // dao.apagar(1);
    }
}

Exercício 7 · Teste JUnit

Adiciona JUnit 5 ao projecto. Cria classe Calculadora com somar, subtrair, dividir (lança ArithmeticException se divisor for 0). Escreve teste para cada método.

Resposta:

pom.xml:

<dependency>
    <groupId>org.junit.jupiter</groupId>
    <artifactId>junit-jupiter</artifactId>
    <version>5.10.0</version>
    <scope>test</scope>
</dependency>

src/main/java/com/exemplo/Calculadora.java:

package com.exemplo;

public class Calculadora {
    public int somar(int a, int b) { return a + b; }
    public int subtrair(int a, int b) { return a - b; }

    public double dividir(double a, double b) {
        if (b == 0) {
            throw new ArithmeticException("Divisão por zero");
        }
        return a / b;
    }
}

src/test/java/com/exemplo/CalculadoraTest.java:

package com.exemplo;

import org.junit.jupiter.api.*;
import static org.junit.jupiter.api.Assertions.*;

class CalculadoraTest {

    private Calculadora calc;

    @BeforeEach
    void setup() {
        calc = new Calculadora();
    }

    @Test
    void somar_doisNumeros_retornaSoma() {
        assertEquals(5, calc.somar(2, 3));
    }

    @Test
    void subtrair_doisNumeros_retornaDiferenca() {
        assertEquals(2, calc.subtrair(5, 3));
    }

    @Test
    void dividir_doisNumeros_retornaQuociente() {
        assertEquals(2.5, calc.dividir(5, 2));
    }

    @Test
    void dividir_porZero_lancaExcepcao() {
        assertThrows(ArithmeticException.class, () -> calc.dividir(5, 0));
    }
}

Correr: mvn test.

Exercício 8 · App CLI — Gestor de tarefas

Cria uma aplicação CLI (loop com menu) que permita: - Adicionar tarefa (com descrição). - Listar todas (com índice). - Marcar como feita. - Apagar. - Sair.

Guarda as tarefas em ArrayList<Tarefa> (sem persistência para simplificar).

Resposta:
import java.util.*;

class Tarefa {
    String descricao;
    boolean feita;

    public Tarefa(String desc) {
        this.descricao = desc;
        this.feita = false;
    }

    @Override
    public String toString() {
        return (feita ? "[x]" : "[ ]") + " " + descricao;
    }
}

public class GestorTarefas {
    private static List<Tarefa> tarefas = new ArrayList<>();
    private static Scanner sc = new Scanner(System.in);

    public static void main(String[] args) {
        boolean continuar = true;
        while (continuar) {
            mostrarMenu();
            int opcao = lerInt("Escolha: ");

            switch (opcao) {
                case 1 -> adicionar();
                case 2 -> listar();
                case 3 -> marcarFeita();
                case 4 -> apagar();
                case 0 -> continuar = false;
                default -> System.out.println("Opção inválida.");
            }
        }
        System.out.println("Adeus!");
    }

    static void mostrarMenu() {
        System.out.println("\n=== GESTOR DE TAREFAS ===");
        System.out.println("1. Adicionar");
        System.out.println("2. Listar");
        System.out.println("3. Marcar como feita");
        System.out.println("4. Apagar");
        System.out.println("0. Sair");
    }

    static void adicionar() {
        System.out.print("Descrição: ");
        String desc = sc.nextLine();
        tarefas.add(new Tarefa(desc));
        System.out.println("Adicionada!");
    }

    static void listar() {
        if (tarefas.isEmpty()) {
            System.out.println("Sem tarefas.");
            return;
        }
        for (int i = 0; i < tarefas.size(); i++) {
            System.out.println(i + ". " + tarefas.get(i));
        }
    }

    static void marcarFeita() {
        listar();
        int idx = lerInt("Índice: ");
        if (idx >= 0 && idx < tarefas.size()) {
            tarefas.get(idx).feita = true;
            System.out.println("Marcada!");
        } else {
            System.out.println("Índice inválido.");
        }
    }

    static void apagar() {
        listar();
        int idx = lerInt("Índice: ");
        if (idx >= 0 && idx < tarefas.size()) {
            tarefas.remove(idx);
            System.out.println("Apagada!");
        } else {
            System.out.println("Índice inválido.");
        }
    }

    static int lerInt(String prompt) {
        System.out.print(prompt);
        int n = sc.nextInt();
        sc.nextLine();  // consumir \n
        return n;
    }
}