Ficha 02 · Java avançado
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;
}
}