Exemplos de Tratamento de Erros Android Java

Exemplos de tratamento de erros Android Java incluindo tratamento de exceções, registro e validação de parâmetros

💻 Validação de Parâmetros java

🟢 simple ⭐⭐

Validar parâmetros de função com validadores personalizados e mensagens de erro

⏱️ 20 min 🏷️ java, android, validation, error handling
Prerequisites: Basic Java knowledge, Validation patterns
// Android Java Parameter Validation Examples
// Comprehensive parameter validation with custom validators

import android.content.Context;
import android.util.Patterns;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;

// 1. Basic Validation Utils
public class ValidationUtils {

    // Null checks
    public static void requireNonNull(Object value, String paramName) {
        if (value == null) {
            throw new IllegalArgumentException(paramName + " cannot be null");
        }
    }

    public static <T> T requireNonNullOrElse(T value, T defaultValue) {
        return value != null ? value : defaultValue;
    }

    // String validation
    public static void requireNonEmpty(String value, String paramName) {
        requireNonNull(value, paramName);
        if (value.isEmpty()) {
            throw new IllegalArgumentException(paramName + " cannot be empty");
        }
    }

    public static void requireNonBlank(String value, String paramName) {
        requireNonNull(value, paramName);
        if (value.trim().isEmpty()) {
            throw new IllegalArgumentException(paramName + " cannot be blank");
        }
    }

    // Number validation
    public static void requirePositive(int value, String paramName) {
        if (value <= 0) {
            throw new IllegalArgumentException(paramName + " must be positive: " + value);
        }
    }

    public static void requirePositive(long value, String paramName) {
        if (value <= 0) {
            throw new IllegalArgumentException(paramName + " must be positive: " + value);
        }
    }

    public static void requireNonNegative(int value, String paramName) {
        if (value < 0) {
            throw new IllegalArgumentException(paramName + " must be non-negative: " + value);
        }
    }

    public static void requireInRange(int value, int min, int max, String paramName) {
        if (value < min || value > max) {
            throw new IllegalArgumentException(
                paramName + " must be between " + min + " and " + max + ": " + value);
        }
    }

    // Collection validation
    public static <T> void requireNonEmpty(Collection<T> collection, String paramName) {
        requireNonNull(collection, paramName);
        if (collection.isEmpty()) {
            throw new IllegalArgumentException(paramName + " cannot be empty");
        }
    }

    public static void requireSize(Collection<?> collection, int expectedSize, String paramName) {
        requireNonNull(collection, paramName);
        if (collection.size() != expectedSize) {
            throw new IllegalArgumentException(
                paramName + " must have exactly " + expectedSize + " elements");
        }
    }

    public static void requireSizeInRange(Collection<?> collection, int min, int max, String paramName) {
        requireNonNull(collection, paramName);
        int size = collection.size();
        if (size < min || size > max) {
            throw new IllegalArgumentException(
                paramName + " must have between " + min + " and " + max + " elements");
        }
    }

    // Array validation
    public static void requireNonEmpty(Object[] array, String paramName) {
        requireNonNull(array, paramName);
        if (array.length == 0) {
            throw new IllegalArgumentException(paramName + " cannot be empty");
        }
    }
}

// 2. String Validators
public class StringValidators {

    // Email validation
    public static boolean isValidEmail(String email) {
        return email != null && Patterns.EMAIL_ADDRESS.matcher(email).matches();
    }

    public static void requireValidEmail(String email, String paramName) {
        ValidationUtils.requireNonNull(email, paramName);
        if (!isValidEmail(email)) {
            throw new IllegalArgumentException(paramName + " must be a valid email: " + email);
        }
    }

    // Phone validation
    public static boolean isValidPhoneNumber(String phone) {
        return phone != null && Patterns.PHONE.matcher(phone).matches();
    }

    public static void requireValidPhoneNumber(String phone, String paramName) {
        ValidationUtils.requireNonNull(phone, paramName);
        if (!isValidPhoneNumber(phone)) {
            throw new IllegalArgumentException(paramName + " must be a valid phone number: " + phone);
        }
    }

    // URL validation
    public static boolean isValidUrl(String url) {
        return url != null && Patterns.WEB_URL.matcher(url).matches();
    }

    public static void requireValidUrl(String url, String paramName) {
        ValidationUtils.requireNonNull(url, paramName);
        if (!isValidUrl(url)) {
            throw new IllegalArgumentException(paramName + " must be a valid URL: " + url);
        }
    }

    // Length validation
    public static boolean hasLength(String str, int minLength, int maxLength) {
        if (str == null) return false;
        int length = str.length();
        return length >= minLength && length <= maxLength;
    }

    public static void requireLength(String str, int minLength, int maxLength, String paramName) {
        ValidationUtils.requireNonNull(str, paramName);
        if (!hasLength(str, minLength, maxLength)) {
            throw new IllegalArgumentException(
                paramName + " must be between " + minLength + " and " + maxLength + " characters");
        }
    }

    // Pattern validation
    public static boolean matchesPattern(String str, String regex) {
        return str != null && Pattern.matches(regex, str);
    }

    public static void requireMatchesPattern(String str, String regex, String paramName) {
        ValidationUtils.requireNonNull(str, paramName);
        if (!matchesPattern(str, regex)) {
            throw new IllegalArgumentException(
                paramName + " must match pattern: " + regex);
        }
    }

    // Numeric string validation
    public static boolean isNumeric(String str) {
        return str != null && str.matches("\\d+");
    }

    public static void requireNumeric(String str, String paramName) {
        ValidationUtils.requireNonNull(str, paramName);
        if (!isNumeric(str)) {
            throw new IllegalArgumentException(paramName + " must be numeric: " + str);
        }
    }

    // Alphanumeric validation
    public static boolean isAlphanumeric(String str) {
        return str != null && str.matches("[a-zA-Z0-9]+");
    }
}

// 3. Validation Result
public class ValidationResult {
    private boolean valid;
    private List<String> errors = new ArrayList<>();

    public ValidationResult(boolean valid) {
        this.valid = valid;
    }

    public static ValidationResult success() {
        return new ValidationResult(true);
    }

    public static ValidationResult failure(String error) {
        ValidationResult result = new ValidationResult(false);
        result.addError(error);
        return result;
    }

    public void addError(String error) {
        errors.add(error);
        valid = false;
    }

    public boolean isValid() {
        return valid;
    }

    public List<String> getErrors() {
        return errors;
    }

    public void throwIfInvalid() {
        if (!valid) {
            throw new IllegalArgumentException(String.join(", ", errors));
        }
    }

    public String getErrorMessage() {
        return String.join("; ", errors);
    }
}

// 4. Validator Builder
public class Validator {
    private String fieldName;
    private Object value;
    private ValidationResult result;

    public Validator(String fieldName, Object value) {
        this.fieldName = fieldName;
        this.value = value;
        this.result = ValidationResult.success();
    }

    public static Validator of(String fieldName, Object value) {
        return new Validator(fieldName, value);
    }

    public Validator notNull() {
        if (value == null) {
            result.addError(fieldName + " cannot be null");
        }
        return this;
    }

    public Validator notEmpty() {
        if (value instanceof String && ((String) value).isEmpty()) {
            result.addError(fieldName + " cannot be empty");
        } else if (value instanceof Collection && ((Collection<?>) value).isEmpty()) {
            result.addError(fieldName + " cannot be empty");
        }
        return this;
    }

    public Validator positive() {
        if (value instanceof Number && ((Number) value).doubleValue() <= 0) {
            result.addError(fieldName + " must be positive");
        }
        return this;
    }

    public Validator nonNegative() {
        if (value instanceof Number && ((Number) value).doubleValue() < 0) {
            result.addError(fieldName + " must be non-negative");
        }
        return this;
    }

    public Validator inRange(int min, int max) {
        if (value instanceof Number) {
            double numValue = ((Number) value).doubleValue();
            if (numValue < min || numValue > max) {
                result.addError(fieldName + " must be between " + min + " and " + max);
            }
        }
        return this;
    }

    public Validator minLength(int minLength) {
        if (value instanceof String && ((String) value).length() < minLength) {
            result.addError(fieldName + " must be at least " + minLength + " characters");
        }
        return this;
    }

    public Validator maxLength(int maxLength) {
        if (value instanceof String && ((String) value).length() > maxLength) {
            result.addError(fieldName + " must be at most " + maxLength + " characters");
        }
        return this;
    }

    public Validator email() {
        if (value instanceof String && !StringValidators.isValidEmail((String) value)) {
            result.addError(fieldName + " must be a valid email");
        }
        return this;
    }

    public Validator matches(String regex) {
        if (value instanceof String && !StringValidators.matchesPattern((String) value, regex)) {
            result.addError(fieldName + " must match pattern: " + regex);
        }
        return this;
    }

    public ValidationResult validate() {
        return result;
    }

    public void throwIfInvalid() {
        result.throwIfInvalid();
    }
}

// 5. User Registration Validator
public class UserRegistrationValidator {

    public static ValidationResult validateRegistration(
        String username,
        String email,
        String password,
        int age) {

        ValidationResult result = ValidationResult.success();

        // Validate username
        Validator.of("username", username)
            .notNull()
            .notEmpty()
            .minLength(3)
            .maxLength(20)
            .matches("^[a-zA-Z0-9_]+$")
            .throwIfInvalid();

        // Validate email
        Validator.of("email", email)
            .notNull()
            .email()
            .throwIfInvalid();

        // Validate password
        Validator.of("password", password)
            .notNull()
            .minLength(8)
            .throwIfInvalid();

        // Password strength
        if (!password.matches(".*[A-Z].*")) {
            result.addError("Password must contain at least one uppercase letter");
        }
        if (!password.matches(".*[a-z].*")) {
            result.addError("Password must contain at least one lowercase letter");
        }
        if (!password.matches(".*\\d.*")) {
            result.addError("Password must contain at least one digit");
        }

        // Validate age
        Validator.of("age", age)
            .inRange(13, 120)
            .throwIfInvalid();

        return result;
    }
}

// 6. Map-based Validation
public class MapValidator {
    private Map<String, Object> data;

    public MapValidator(Map<String, Object> data) {
        this.data = data;
    }

    public ValidationResult validate(String fieldName, boolean required, Class<?> type) {
        ValidationResult result = ValidationResult.success();

        Object value = data.get(fieldName);

        if (value == null) {
            if (required) {
                result.addError(fieldName + " is required");
            }
        } else if (type != null && !type.isInstance(value)) {
            result.addError(fieldName + " must be of type " + type.getSimpleName());
        }

        return result;
    }

    public ValidationResult validateString(String fieldName, boolean required, int minLength, int maxLength) {
        ValidationResult result = ValidationResult.success();

        Object value = data.get(fieldName);

        if (value == null) {
            if (required) {
                result.addError(fieldName + " is required");
            }
        } else if (value instanceof String) {
            String strValue = (String) value;
            if (strValue.length() < minLength) {
                result.addError(fieldName + " must be at least " + minLength + " characters");
            }
            if (strValue.length() > maxLength) {
                result.addError(fieldName + " must be at most " + maxLength + " characters");
            }
        } else {
            result.addError(fieldName + " must be a string");
        }

        return result;
    }
}

// 7. Assert-style Validation
public class Assert {

    public static void isTrue(boolean condition, String message) {
        if (!condition) {
            throw new IllegalArgumentException(message);
        }
    }

    public static void isFalse(boolean condition, String message) {
        if (condition) {
            throw new IllegalArgumentException(message);
        }
    }

    public static void equals(Object expected, Object actual, String message) {
        if (expected == null && actual == null) {
            return;
        }
        if (expected == null || !expected.equals(actual)) {
            throw new IllegalArgumentException(message + " (expected: " + expected + ", actual: " + actual + ")");
        }
    }

    public static void notEquals(Object unexpected, Object actual, String message) {
        if (unexpected == null && actual == null) {
            throw new IllegalArgumentException(message);
        }
        if (unexpected != null && unexpected.equals(actual)) {
            throw new IllegalArgumentException(message);
        }
    }
}

// Main demonstration
public class ParameterValidationDemo {
    public static void demonstrateParameterValidation() {
        System.out.println("=== Android Java Parameter Validation Examples ===\n");

        // 1. Basic validation
        System.out.println("--- 1. Basic Validation ---");

        try {
            ValidationUtils.requireNonNull("test", "param");
            System.out.println("✓ Not null check passed");
        } catch (Exception e) {
            System.out.println("✗ " + e.getMessage());
        }

        try {
            ValidationUtils.requireNonNull(null, "param");
            System.out.println("✓ Should not reach here");
        } catch (Exception e) {
            System.out.println("✓ Caught null: " + e.getMessage());
        }

        try {
            ValidationUtils.requireInRange(15, 10, 20, "age");
            System.out.println("✓ Range check passed");
        } catch (Exception e) {
            System.out.println("✗ " + e.getMessage());
        }

        // 2. String validation
        System.out.println("\n--- 2. String Validation ---");

        System.out.println("Valid email '[email protected]': " + StringValidators.isValidEmail("[email protected]"));
        System.out.println("Invalid email 'invalid': " + StringValidators.isValidEmail("invalid"));

        System.out.println("Valid phone '+1234567890': " + StringValidators.isValidPhoneNumber("+1234567890"));
        System.out.println("Valid URL 'https://example.com': " + StringValidators.isValidUrl("https://example.com"));

        // 3. Validator builder
        System.out.println("\n--- 3. Validator Builder ---");

        ValidationResult nameResult = Validator.of("username", "john_doe")
            .notNull()
            .minLength(3)
            .maxLength(20)
            .validate();
        System.out.println("Username validation: " + (nameResult.isValid() ? "✓" : "✗"));

        ValidationResult shortName = Validator.of("username", "jo")
            .minLength(3)
            .validate();
        System.out.println("Short username: " + (shortName.isValid() ? "✓" : "✗"));
        if (!shortName.isValid()) {
            System.out.println("  Errors: " + shortName.getErrorMessage());
        }

        // 4. User registration validation
        System.out.println("\n--- 4. User Registration Validation ---");

        ValidationResult validRegistration = UserRegistrationValidator.validateRegistration(
            "john_doe",
            "[email protected]",
            "Password123",
            25
        );
        System.out.println("Valid registration: " + (validRegistration.isValid() ? "✓" : "✗"));

        ValidationResult invalidRegistration = UserRegistrationValidator.validateRegistration(
            "jo",
            "invalid-email",
            "weak",
            10
        );
        System.out.println("Invalid registration: " + (invalidRegistration.isValid() ? "✓" : "✗"));
        if (!invalidRegistration.isValid()) {
            System.out.println("  Errors:");
            for (String error : invalidRegistration.getErrors()) {
                System.out.println("    - " + error);
            }
        }

        // 5. Assert validation
        System.out.println("\n--- 5. Assert Validation ---");

        try {
            Assert.isTrue(1 > 0, "1 should be greater than 0");
            System.out.println("✓ Assert.isTrue passed");
        } catch (Exception e) {
            System.out.println("✗ " + e.getMessage());
        }

        try {
            Assert.equals("hello", "hello", "Strings should be equal");
            System.out.println("✓ Assert.equals passed");
        } catch (Exception e) {
            System.out.println("✗ " + e.getMessage());
        }

        try {
            Assert.equals("hello", "world", "Strings should be equal");
            System.out.println("✗ Should not reach here");
        } catch (Exception e) {
            System.out.println("✓ Assert.equals failed: " + e.getMessage());
        }

        System.out.println("\n=== All Parameter Validation Examples Completed ===");
    }
}

💻 Tratamento de Exceções java

🟡 intermediate ⭐⭐⭐

Tratamento de exceções try-catch com múltiplos tipos de exceções e exceções personalizadas

⏱️ 30 min 🏷️ java, android, error handling
Prerequisites: Intermediate Java, Exception hierarchy
// Android Java Exception Handling Examples
// Using try-catch, throw, and custom exceptions

import android.content.Context;
import java.io.*;
import java.util.ArrayList;
import java.util.List;

// 1. Basic Try-Catch
public class BasicExceptionHandling {

    // Simple try-catch
    public int divideNumbers(int a, int b) {
        try {
            return a / b;
        } catch (ArithmeticException e) {
            System.out.println("Division by zero: " + e.getMessage());
            return 0;
        }
    }

    // Try-catch with finally
    public String readFile(String filename) {
        FileInputStream input = null;
        try {
            input = new FileInputStream(filename);
            StringBuilder content = new StringBuilder();
            int data;
            while ((data = input.read()) != -1) {
                content.append((char) data);
            }
            return content.toString();
        } catch (IOException e) {
            System.out.println("Error reading file: " + e.getMessage());
            return null;
        } finally {
            if (input != null) {
                try {
                    input.close();
                } catch (IOException e) {
                    System.out.println("Error closing file: " + e.getMessage());
                }
            }
        }
    }

    // Multiple catch blocks
    public void processFile(String filename) {
        try {
            FileInputStream input = new FileInputStream(filename);
            // Process file
            input.close();
        } catch (FileNotFoundException e) {
            System.out.println("File not found: " + filename);
        } catch (IOException e) {
            System.out.println("IO error: " + e.getMessage());
        } catch (Exception e) {
            System.out.println("Unexpected error: " + e.getMessage());
        }
    }

    // Try-with-resources
    public void readFileWithResources(String filename) {
        try (FileInputStream input = new FileInputStream(filename);
             BufferedReader reader = new BufferedReader(new InputStreamReader(input))) {
            String line;
            while ((line = reader.readLine()) != null) {
                System.out.println(line);
            }
        } catch (IOException e) {
            System.out.println("Error reading file: " + e.getMessage());
        }
    }
}

// 2. Custom Exceptions
class InvalidAgeException extends Exception {
    public InvalidAgeException(String message) {
        super(message);
    }
}

class InsufficientFundsException extends Exception {
    private double amount;
    private double balance;

    public InsufficientFundsException(double amount, double balance) {
        super("Insufficient funds: attempted to withdraw " + amount + " but balance is " + balance);
        this.amount = amount;
        this.balance = balance;
    }

    public double getAmount() {
        return amount;
    }

    public double getBalance() {
        return balance;
    }
}

// 3. Exception Handling in Practice
public class UserService {

    // Validate and throw custom exception
    public void setAge(int age) throws InvalidAgeException {
        if (age < 0) {
            throw new InvalidAgeException("Age cannot be negative: " + age);
        }
        if (age > 150) {
            throw new InvalidAgeException("Age cannot exceed 150: " + age);
        }
        System.out.println("Age set to: " + age);
    }

    // Safe method with error handling
    public boolean trySetAge(int age) {
        try {
            setAge(age);
            return true;
        } catch (InvalidAgeException e) {
            System.out.println("Invalid age: " + e.getMessage());
            return false;
        }
    }

    // Chain exceptions
    public void loadUserData(String userId) {
        try {
            // Simulate loading user data
            if (userId == null || userId.isEmpty()) {
                throw new IllegalArgumentException("User ID cannot be empty");
            }
            // Load data...
        } catch (IllegalArgumentException e) {
            throw new RuntimeException("Failed to load user data", e);
        }
    }
}

// 4. Bank Account with Exception Handling
public class BankAccount {
    private double balance;
    private String accountNumber;

    public BankAccount(String accountNumber, double initialBalance) {
        this.accountNumber = accountNumber;
        this.balance = initialBalance;
    }

    // Withdraw with exception
    public void withdraw(double amount) throws InsufficientFundsException {
        if (amount <= 0) {
            throw new IllegalArgumentException("Withdrawal amount must be positive");
        }
        if (amount > balance) {
            throw new InsufficientFundsException(amount, balance);
        }
        balance -= amount;
        System.out.println("Withdrew: " + amount + ", New balance: " + balance);
    }

    // Safe withdraw
    public boolean tryWithdraw(double amount) {
        try {
            withdraw(amount);
            return true;
        } catch (InsufficientFundsException | IllegalArgumentException e) {
            System.out.println("Withdrawal failed: " + e.getMessage());
            return false;
        }
    }

    public double getBalance() {
        return balance;
    }
}

// 5. Exception Collecting
public class ExceptionCollector {
    private List<Exception> exceptions = new ArrayList<>();

    public void addException(Exception e) {
        exceptions.add(e);
    }

    public boolean hasExceptions() {
        return !exceptions.isEmpty();
    }

    public void printExceptions() {
        if (hasExceptions()) {
            System.out.println("\n=== Exceptions Collected ===");
            for (int i = 0; i < exceptions.size(); i++) {
                System.out.println((i + 1) + ". " + exceptions.get(i).getMessage());
            }
        }
    }

    public void clear() {
        exceptions.clear();
    }
}

// 6. Batch Processing with Error Handling
public class BatchProcessor {

    public static class BatchResult {
        public int successCount = 0;
        public int failureCount = 0;
        public List<String> errors = new ArrayList<>();

        public void printSummary() {
            System.out.println("\n=== Batch Processing Summary ===");
            System.out.println("Success: " + successCount);
            System.out.println("Failed: " + failureCount);
            if (!errors.isEmpty()) {
                System.out.println("\nErrors:");
                for (String error : errors) {
                    System.out.println("  - " + error);
                }
            }
        }
    }

    // Process items with error collection
    public BatchResult processItems(List<String> items) {
        BatchResult result = new BatchResult();

        for (String item : items) {
            try {
                processItem(item);
                result.successCount++;
            } catch (Exception e) {
                result.failureCount++;
                result.errors.add(item + ": " + e.getMessage());
            }
        }

        return result;
    }

    private void processItem(String item) throws Exception {
        if (item == null || item.isEmpty()) {
            throw new IllegalArgumentException("Item cannot be empty");
        }
        if (item.startsWith("error")) {
            throw new Exception("Simulated error for: " + item);
        }
        System.out.println("Processed: " + item);
    }
}

// 7. Retry Mechanism
public class RetryHandler {

    public interface RetryableOperation<T> {
        T execute() throws Exception;
    }

    // Execute with retry
    public <T> T executeWithRetry(RetryableOperation<T> operation, int maxRetries) throws Exception {
        Exception lastException = null;

        for (int attempt = 1; attempt <= maxRetries; attempt++) {
            try {
                return operation.execute();
            } catch (Exception e) {
                lastException = e;
                System.out.println("Attempt " + attempt + " failed: " + e.getMessage());

                if (attempt < maxRetries) {
                    long delay = (long) Math.pow(2, attempt) * 100; // Exponential backoff
                    System.out.println("Retrying in " + delay + "ms...");
                    Thread.sleep(delay);
                }
            }
        }

        throw new Exception("Operation failed after " + maxRetries + " attempts", lastException);
    }

    // Safe execute with retry
    public <T> T safeExecuteWithRetry(RetryableOperation<T> operation, int maxRetries, T defaultValue) {
        try {
            return executeWithRetry(operation, maxRetries);
        } catch (Exception e) {
            System.out.println("All retry attempts failed: " + e.getMessage());
            return defaultValue;
        }
    }
}

// 8. Exception Utils
public class ExceptionUtils {

    // Get full stack trace as string
    public static String getStackTrace(Throwable throwable) {
        StringWriter sw = new StringWriter();
        PrintWriter pw = new PrintWriter(sw);
        throwable.printStackTrace(pw);
        return sw.toString();
    }

    // Get root cause
    public static Throwable getRootCause(Throwable throwable) {
        Throwable cause = throwable;
        while (cause.getCause() != null) {
            cause = cause.getCause();
        }
        return cause;
    }

    // Print root cause
    public static void printRootCause(Throwable throwable) {
        Throwable rootCause = getRootCause(throwable);
        System.out.println("Root cause: " + rootCause.getClass().getName() + ": " + rootCause.getMessage());
    }
}

// Main demonstration
public class ExceptionHandlingDemo {
    public static void demonstrateExceptionHandling() {
        System.out.println("=== Android Java Exception Handling Examples ===\n");

        // 1. Basic exception handling
        System.out.println("--- 1. Basic Exception Handling ---");
        BasicExceptionHandling basic = new BasicExceptionHandling();

        System.out.println("10 / 2 = " + basic.divideNumbers(10, 2));
        System.out.println("10 / 0 = " + basic.divideNumbers(10, 0));

        // 2. Custom exceptions
        System.out.println("\n--- 2. Custom Exceptions ---");
        UserService userService = new UserService();

        try {
            userService.setAge(25);
            userService.setAge(-5); // Will throw
        } catch (InvalidAgeException e) {
            System.out.println("Caught: " + e.getMessage());
        }

        // 3. Bank account with exceptions
        System.out.println("\n--- 3. Bank Account Exceptions ---");
        BankAccount account = new BankAccount("12345", 1000.0);

        account.tryWithdraw(500.0);
        account.tryWithdraw(600.0); // Will fail - insufficient funds
        account.tryWithdraw(-100.0); // Will fail - invalid amount

        // 4. Batch processing
        System.out.println("\n--- 4. Batch Processing with Error Handling ---");
        BatchProcessor processor = new BatchProcessor();

        List<String> items = new ArrayList<>();
        items.add("item1");
        items.add("item2");
        items.add("error1");
        items.add("item3");
        items.add("");
        items.add("error2");

        BatchProcessor.BatchResult result = processor.processItems(items);
        result.printSummary();

        // 5. Retry mechanism
        System.out.println("\n--- 5. Retry Mechanism ---");
        RetryHandler retryHandler = new RetryHandler();

        // Successful after retries
        RetryHandler.RetryableOperation<Integer> operation = new RetryHandler.RetryableOperation<Integer>() {
            private int attempts = 0;

            @Override
            public Integer execute() throws Exception {
                attempts++;
                if (attempts < 3) {
                    throw new Exception("Temporary failure");
                }
                return 42;
            }
        };

        Integer value = retryHandler.safeExecuteWithRetry(operation, 5, -1);
        System.out.println("Operation result: " + value);

        // 6. Exception utils
        System.out.println("\n--- 6. Exception Utilities ---");
        try {
            throw new Exception("Outer exception", new RuntimeException("Inner exception", new IllegalArgumentException("Root cause")));
        } catch (Exception e) {
            System.out.println("Full stack trace:");
            System.out.println(ExceptionUtils.getStackTrace(e));
            ExceptionUtils.printRootCause(e);
        }

        System.out.println("\n=== All Exception Handling Examples Completed ===");
    }
}

💻 Registro de Logs java

🟡 intermediate ⭐⭐⭐

Escrever logs em arquivos com diferentes níveis, formatos e estratégias de rotação

⏱️ 25 min 🏷️ java, android, logging, error handling
Prerequisites: Intermediate Java, Android logging
// Android Java Logging Examples
// Using android.util.Log and file-based logging

import android.content.Context;
import android.util.Log;
import java.io.*;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;

// 1. Android LogCat Logging
public class LogCatLogger {

    private static final String TAG = "MyApp";

    // Basic logging levels
    public void logVerbose(String message) {
        Log.v(TAG, message);
    }

    public void logDebug(String message) {
        Log.d(TAG, message);
    }

    public void logInfo(String message) {
        Log.i(TAG, message);
    }

    public void logWarning(String message) {
        Log.w(TAG, message);
    }

    public void logError(String message) {
        Log.e(TAG, message);
    }

    // Logging with exception
    public void logException(String message, Throwable throwable) {
        Log.e(TAG, message, throwable);
    }

    // Conditional logging
    public void logDebugIf(boolean condition, String message) {
        if (condition) {
            Log.d(TAG, message);
        }
    }

    // Logging with formatting
    public void logFormatted(String message, Object... args) {
        Log.d(TAG, String.format(message, args));
    }
}

// 2. File Logger
public class FileLogger {
    private Context context;
    private String logFileName;
    private boolean consoleOutput;

    public FileLogger(Context context, String logFileName) {
        this.context = context;
        this.logFileName = logFileName;
        this.consoleOutput = false;
    }

    public void setConsoleOutput(boolean enabled) {
        this.consoleOutput = enabled;
    }

    // Log levels
    public enum LogLevel {
        VERBOSE, DEBUG, INFO, WARNING, ERROR
    }

    // Write log to file
    public void log(LogLevel level, String tag, String message) {
        String timestamp = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS", Locale.getDefault()).format(new Date());
        String logEntry = String.format("[%s] [%s] [%s] %s%n", timestamp, level, tag, message);

        try {
            FileOutputStream output = context.openFileOutput(logFileName, Context.MODE_APPEND);
            output.write(logEntry.getBytes());
            output.close();

            if (consoleOutput) {
                System.out.print(logEntry);
            }
        } catch (IOException e) {
            Log.e("FileLogger", "Failed to write log", e);
        }
    }

    public void verbose(String tag, String message) {
        log(LogLevel.VERBOSE, tag, message);
    }

    public void debug(String tag, String message) {
        log(LogLevel.DEBUG, tag, message);
    }

    public void info(String tag, String message) {
        log(LogLevel.INFO, tag, message);
    }

    public void warning(String tag, String message) {
        log(LogLevel.WARNING, tag, message);
    }

    public void error(String tag, String message) {
        log(LogLevel.ERROR, tag, message);
    }

    public void error(String tag, String message, Throwable throwable) {
        String fullMessage = message + "\n" + Log.getStackTraceString(throwable);
        log(LogLevel.ERROR, tag, fullMessage);
    }

    // Read all logs
    public String readLogs() {
        try {
            FileInputStream input = context.openFileInput(logFileName);
            BufferedReader reader = new BufferedReader(new InputStreamReader(input));
            StringBuilder logs = new StringBuilder();
            String line;
            while ((line = reader.readLine()) != null) {
                logs.append(line).append("\n");
            }
            reader.close();
            return logs.toString();
        } catch (IOException e) {
            return "Error reading logs: " + e.getMessage();
        }
    }

    // Clear logs
    public void clearLogs() {
        context.deleteFile(logFileName);
    }

    // Get log file size
    public long getLogSize() {
        File file = new File(context.getFilesDir(), logFileName);
        return file.exists() ? file.length() : 0;
    }
}

// 3. Logger with Rotation
public class RotatingFileLogger {
    private Context context;
    private String baseLogFileName;
    private long maxFileSize;
    private int maxBackupFiles;
    private String currentLogFile;

    public RotatingFileLogger(Context context, String baseFileName, long maxFileSize, int maxBackupFiles) {
        this.context = context;
        this.baseLogFileName = baseFileName;
        this.maxFileSize = maxFileSize;
        this.maxBackupFiles = maxBackupFiles;
        this.currentLogFile = baseFileName;
    }

    public enum LogLevel {
        VERBOSE, DEBUG, INFO, WARNING, ERROR
    }

    public void log(LogLevel level, String tag, String message) {
        checkRotation();

        String timestamp = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS", Locale.getDefault()).format(new Date());
        String logEntry = String.format("[%s] [%s] [%s] %s%n", timestamp, level, tag, message);

        try {
            FileOutputStream output = context.openFileOutput(currentLogFile, Context.MODE_APPEND);
            output.write(logEntry.getBytes());
            output.close();
        } catch (IOException e) {
            Log.e("RotatingFileLogger", "Failed to write log", e);
        }
    }

    private void checkRotation() {
        File file = new File(context.getFilesDir(), currentLogFile);

        if (file.exists() && file.length() >= maxFileSize) {
            rotateLogs();
        }
    }

    private void rotateLogs() {
        // Delete oldest backup if it exists
        File oldestBackup = new File(context.getFilesDir(), baseLogFileName + "." + maxBackupFiles);
        if (oldestBackup.exists()) {
            oldestBackup.delete();
        }

        // Rotate existing backups
        for (int i = maxBackupFiles - 1; i >= 1; i--) {
            File oldFile = new File(context.getFilesDir(), baseLogFileName + "." + i);
            File newFile = new File(context.getFilesDir(), baseLogFileName + "." + (i + 1));

            if (oldFile.exists()) {
                oldFile.renameTo(newFile);
            }
        }

        // Rename current log to .1
        File currentFile = new File(context.getFilesDir(), currentLogFile);
        File backupFile = new File(context.getFilesDir(), baseLogFileName + ".1");

        if (currentFile.exists()) {
            currentFile.renameTo(backupFile);
        }
    }

    // Convenience methods
    public void debug(String tag, String message) {
        log(LogLevel.DEBUG, tag, message);
    }

    public void info(String tag, String message) {
        log(LogLevel.INFO, tag, message);
    }

    public void warning(String tag, String message) {
        log(LogLevel.WARNING, tag, message);
    }

    public void error(String tag, String message) {
        log(LogLevel.ERROR, tag, message);
    }
}

// 4. Structured Logger
public class StructuredLogger {
    private FileLogger fileLogger;

    public StructuredLogger(Context context, String logFileName) {
        this.fileLogger = new FileLogger(context, logFileName);
    }

    public enum LogLevel {
        VERBOSE, DEBUG, INFO, WARNING, ERROR
    }

    // Log structured data
    public void log(LogLevel level, String tag, String message, java.util.Map<String, Object> metadata) {
        StringBuilder logMessage = new StringBuilder();
        logMessage.append(message);

        if (metadata != null && !metadata.isEmpty()) {
            logMessage.append(" | ");
            for (java.util.Map.Entry<String, Object> entry : metadata.entrySet()) {
                logMessage.append(entry.getKey()).append("=").append(entry.getValue()).append(", ");
            }
            // Remove trailing comma
            if (logMessage.length() > 2) {
                logMessage.setLength(logMessage.length() - 2);
            }
        }

        fileLogger.log(level, tag, logMessage.toString());
    }

    // Log user action
    public void logUserAction(String action, String userId, java.util.Map<String, Object> details) {
        java.util.Map<String, Object> metadata = new java.util.HashMap<>();
        metadata.put("userId", userId);
        if (details != null) {
            metadata.putAll(details);
        }
        log(LogLevel.INFO, "USER_ACTION", action, metadata);
    }

    // Log error with context
    public void logError(String message, Throwable error, java.util.Map<String, Object> context) {
        java.util.Map<String, Object> metadata = new java.util.HashMap<>();
        metadata.put("errorType", error.getClass().getSimpleName());
        metadata.put("errorMessage", error.getMessage());
        if (context != null) {
            metadata.putAll(context);
        }
        log(LogLevel.ERROR, "ERROR", message, metadata);
    }
}

// 5. Performance Logger
public class PerformanceLogger {
    private FileLogger logger;
    private java.util.Map<String, Long> startTimes = new java.util.HashMap<>();

    public PerformanceLogger(Context context) {
        this.logger = new FileLogger(context, "performance.log");
    }

    // Start timing
    public void startTiming(String operation) {
        startTimes.put(operation, System.currentTimeMillis());
        logger.debug("PERF", "Started: " + operation);
    }

    // End timing
    public void endTiming(String operation) {
        Long startTime = startTimes.get(operation);
        if (startTime != null) {
            long duration = System.currentTimeMillis() - startTime;
            logger.info("PERF", String.format("Completed: %s in %d ms", operation, duration));
            startTimes.remove(operation);
        }
    }

    // Log memory usage
    public void logMemoryUsage(String tag) {
        Runtime runtime = Runtime.getRuntime();
        long usedMemory = runtime.totalMemory() - runtime.freeMemory();
        long maxMemory = runtime.maxMemory();
        long percentUsed = (usedMemory * 100) / maxMemory;

        logger.info("MEMORY", String.format("[%s] Used: %d MB, Max: %d MB (%d%%)",
            tag,
            usedMemory / (1024 * 1024),
            maxMemory / (1024 * 1024),
            percentUsed));
    }
}

// 6. Log Viewer
public class LogViewer {
    private Context context;
    private String logFileName;

    public LogViewer(Context context, String logFileName) {
        this.context = context;
        this.logFileName = logFileName;
    }

    // Filter logs by level
    public String filterLogs(FileLogger.LogLevel level) {
        try {
            FileInputStream input = context.openFileInput(logFileName);
            BufferedReader reader = new BufferedReader(new InputStreamReader(input));
            StringBuilder filtered = new StringBuilder();
            String line;

            while ((line = reader.readLine()) != null) {
                if (line.contains("[" + level + "]")) {
                    filtered.append(line).append("\n");
                }
            }

            reader.close();
            return filtered.toString();
        } catch (IOException e) {
            return "Error filtering logs: " + e.getMessage();
        }
    }

    // Get last N lines
    public String getLastLines(int count) {
        try {
            FileInputStream input = context.openFileInput(logFileName);
            BufferedReader reader = new BufferedReader(new InputStreamReader(input));

            java.util.List<String> lines = new java.util.ArrayList<>();
            String line;
            while ((line = reader.readLine()) != null) {
                lines.add(line);
            }
            reader.close();

            // Get last N lines
            int start = Math.max(0, lines.size() - count);
            StringBuilder result = new StringBuilder();
            for (int i = start; i < lines.size(); i++) {
                result.append(lines.get(i)).append("\n");
            }

            return result.toString();
        } catch (IOException e) {
            return "Error reading logs: " + e.getMessage();
        }
    }

    // Search logs
    public String searchLogs(String searchText) {
        try {
            FileInputStream input = context.openFileInput(logFileName);
            BufferedReader reader = new BufferedReader(new InputStreamReader(input));
            StringBuilder results = new StringBuilder();
            String line;

            while ((line = reader.readLine()) != null) {
                if (line.toLowerCase().contains(searchText.toLowerCase())) {
                    results.append(line).append("\n");
                }
            }

            reader.close();
            return results.toString();
        } catch (IOException e) {
            return "Error searching logs: " + e.getMessage();
        }
    }
}

// Main demonstration
public class LoggingDemo {
    public static void demonstrateLogging(Context context) {
        System.out.println("=== Android Java Logging Examples ===\n");

        // 1. LogCat logging
        System.out.println("--- 1. LogCat Logging ---");
        LogCatLogger logCatLogger = new LogCatLogger();

        logCatLogger.logVerbose("This is a verbose message");
        logCatLogger.logDebug("This is a debug message");
        logCatLogger.logInfo("This is an info message");
        logCatLogger.logWarning("This is a warning message");
        logCatLogger.logError("This is an error message");
        logCatLogger.logFormatted("Formatted: %s + %d = %.2f", "test", 42, 3.14);

        // 2. File logging
        System.out.println("\n--- 2. File Logging ---");
        FileLogger fileLogger = new FileLogger(context, "app.log");
        fileLogger.setConsoleOutput(true);

        fileLogger.debug("MyApp", "Application started");
        fileLogger.info("MyApp", "User logged in");
        fileLogger.warning("MyApp", "High memory usage detected");
        fileLogger.error("MyApp", "Failed to load data");

        // Log with exception
        try {
            throw new RuntimeException("Test exception");
        } catch (Exception e) {
            fileLogger.error("MyApp", "An error occurred", e);
        }

        // Read logs
        System.out.println("\nFile logs:");
        System.out.println(fileLogger.readLogs());
        System.out.println("Log file size: " + fileLogger.getLogSize() + " bytes");

        // 3. Rotating file logger
        System.out.println("\n--- 3. Rotating File Logger ---");
        RotatingFileLogger rotatingLogger = new RotatingFileLogger(context, "rotating.log", 1024, 3);

        for (int i = 0; i < 10; i++) {
            rotatingLogger.info("MyApp", "Log entry " + i);
        }

        // 4. Structured logging
        System.out.println("\n--- 4. Structured Logging ---");
        StructuredLogger structuredLogger = new StructuredLogger(context, "structured.log");
        structuredLogger.setConsoleOutput(true);

        java.util.Map<String, Object> metadata = new java.util.HashMap<>();
        metadata.put("userId", "12345");
        metadata.put("action", "login");
        metadata.put("ip", "192.168.1.1");

        structuredLogger.log(StructuredLogger.LogLevel.INFO, "AUTH", "User login successful", metadata);

        structuredLogger.logUserAction("purchase", "user123", metadata);
        structuredLogger.logError("Payment failed", new Exception("Insufficient funds"), null);

        // 5. Performance logging
        System.out.println("\n--- 5. Performance Logging ---");
        PerformanceLogger perfLogger = new PerformanceLogger(context);
        perfLogger.setConsoleOutput(true);

        perfLogger.startTiming("database query");
        // Simulate operation
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            // Ignore
        }
        perfLogger.endTiming("database query");

        perfLogger.logMemoryUsage("After operation");

        // 6. Log viewer
        System.out.println("\n--- 6. Log Viewer ---");
        LogViewer logViewer = new LogViewer(context, "app.log");

        System.out.println("\nLast 5 lines:");
        System.out.println(logViewer.getLastLines(5));

        System.out.println("Search for 'error':");
        System.out.println(logViewer.searchLogs("error"));

        System.out.println("\n=== All Logging Examples Completed ===");
    }
}