Java Programming Examples
Complete Applications & Practical Implementation
Chapter 13: Real-World Java Programming
Comprehensive examples integrating all Java concepts
Student Management System
Core Classes Design
// Student.java
public class Student {
private String id;
private String name;
private String email;
private List<Course> courses;
private Map<String, Grade> grades;
public Student(String id, String name, String email) {
this.id = id;
this.name = name;
this.email = email;
this.courses = new ArrayList<>();
this.grades = new HashMap<>();
}
public void enrollInCourse(Course course) {
if (!courses.contains(course)) {
courses.add(course);
course.addStudent(this);
}
}
public void addGrade(String courseId, Grade grade) {
grades.put(courseId, grade);
}
public double calculateGPA() {
if (grades.isEmpty()) return 0.0;
double totalPoints = 0;
int totalCredits = 0;
for (Map.Entry<String, Grade> entry : grades.entrySet()) {
Grade grade = entry.getValue();
totalPoints += grade.getPoints() * grade.getCredits();
totalCredits += grade.getCredits();
}
return totalCredits > 0 ? totalPoints / totalCredits : 0.0;
}
// Getters and setters...
}
Course & Grade Classes
// Course.java
public class Course {
private String courseId;
private String title;
private int credits;
private String instructor;
private List<Student> enrolledStudents;
private int maxCapacity;
public Course(String courseId, String title,
int credits, String instructor, int maxCapacity) {
this.courseId = courseId;
this.title = title;
this.credits = credits;
this.instructor = instructor;
this.maxCapacity = maxCapacity;
this.enrolledStudents = new ArrayList<>();
}
public boolean addStudent(Student student) {
if (enrolledStudents.size() < maxCapacity &&
!enrolledStudents.contains(student)) {
enrolledStudents.add(student);
return true;
}
return false;
}
public List<Student> getEnrolledStudents() {
return new ArrayList<>(enrolledStudents);
}
}
// Grade.java
public class Grade {
private double points; // 4.0 scale
private int credits;
private String letterGrade;
public Grade(double points, int credits) {
this.points = points;
this.credits = credits;
this.letterGrade = calculateLetterGrade(points);
}
private String calculateLetterGrade(double points) {
if (points >= 3.7) return "A";
else if (points >= 3.3) return "A-";
else if (points >= 3.0) return "B+";
else if (points >= 2.7) return "B";
else if (points >= 2.3) return "B-";
else if (points >= 2.0) return "C+";
else if (points >= 1.7) return "C";
else if (points >= 1.3) return "C-";
else if (points >= 1.0) return "D";
else return "F";
}
}
StudentManager Implementation
// StudentManager.java
import java.util.*;
import java.util.stream.Collectors;
public class StudentManager {
private Map<String, Student> students;
private Map<String, Course> courses;
private static final String DATA_FILE = "students.dat";
public StudentManager() {
students = new HashMap<>();
courses = new HashMap<>();
loadData();
}
public void addStudent(Student student) {
students.put(student.getId(), student);
saveData();
}
public void addCourse(Course course) {
courses.put(course.getCourseId(), course);
saveData();
}
public boolean enrollStudent(String studentId, String courseId) {
Student student = students.get(studentId);
Course course = courses.get(courseId);
if (student != null && course != null) {
student.enrollInCourse(course);
saveData();
return true;
}
return false;
}
public void recordGrade(String studentId, String courseId, double points, int credits) {
Student student = students.get(studentId);
if (student != null) {
Grade grade = new Grade(points, credits);
student.addGrade(courseId, grade);
saveData();
}
}
public List<Student> getTopStudents(int count) {
return students.values().stream()
.sorted((s1, s2) -> Double.compare(s2.calculateGPA(), s1.calculateGPA()))
.limit(count)
.collect(Collectors.toList());
}
public List<Student> searchStudents(String searchTerm) {
return students.values().stream()
.filter(s -> s.getName().toLowerCase().contains(searchTerm.toLowerCase()) ||
s.getEmail().toLowerCase().contains(searchTerm.toLowerCase()))
.collect(Collectors.toList());
}
public Map<String, Long> getCourseEnrollmentStats() {
return courses.values().stream()
.collect(Collectors.toMap(
Course::getTitle,
course -> (long) course.getEnrolledStudents().size()
));
}
// File I/O methods
private void saveData() {
try (ObjectOutputStream oos = new ObjectOutputStream(
new FileOutputStream(DATA_FILE))) {
oos.writeObject(students);
oos.writeObject(courses);
} catch (IOException e) {
System.err.println("Error saving data: " + e.getMessage());
}
}
@SuppressWarnings("unchecked")
private void loadData() {
try (ObjectInputStream ois = new ObjectInputStream(
new FileInputStream(DATA_FILE))) {
students = (Map<String, Student>) ois.readObject();
courses = (Map<String, Course>) ois.readObject();
} catch (IOException | ClassNotFoundException e) {
// File doesn't exist or is corrupted, start fresh
students = new HashMap<>();
courses = new HashMap<>();
}
}
}
Banking System with Transactions
Account Hierarchy
// Account.java (Abstract Base Class)
public abstract class Account {
protected String accountNumber;
protected String holderName;
protected double balance;
protected List<Transaction> transactions;
protected final Object lock = new Object();
public Account(String accountNumber, String holderName,
double initialBalance) {
this.accountNumber = accountNumber;
this.holderName = holderName;
this.balance = initialBalance;
this.transactions = new ArrayList<>();
}
public synchronized boolean deposit(double amount) {
if (amount <= 0) {
throw new IllegalArgumentException("Deposit amount must be positive");
}
balance += amount;
Transaction transaction = new Transaction(
TransactionType.DEPOSIT, amount, balance
);
transactions.add(transaction);
return true;
}
public synchronized boolean withdraw(double amount) {
if (amount <= 0) {
throw new IllegalArgumentException("Withdrawal amount must be positive");
}
if (canWithdraw(amount)) {
balance -= amount;
Transaction transaction = new Transaction(
TransactionType.WITHDRAWAL, amount, balance
);
transactions.add(transaction);
return true;
}
return false;
}
protected abstract boolean canWithdraw(double amount);
public synchronized double getBalance() {
return balance;
}
public List<Transaction> getTransactionHistory() {
synchronized(lock) {
return new ArrayList<>(transactions);
}
}
}
Specific Account Types
// SavingsAccount.java
public class SavingsAccount extends Account {
private double interestRate;
private int withdrawalCount;
private static final int MAX_WITHDRAWALS = 6;
public SavingsAccount(String accountNumber, String holderName,
double initialBalance, double interestRate) {
super(accountNumber, holderName, initialBalance);
this.interestRate = interestRate;
this.withdrawalCount = 0;
}
@Override
protected boolean canWithdraw(double amount) {
return balance >= amount && withdrawalCount < MAX_WITHDRAWALS;
}
@Override
public synchronized boolean withdraw(double amount) {
if (super.withdraw(amount)) {
withdrawalCount++;
return true;
}
return false;
}
public void applyMonthlyInterest() {
synchronized(lock) {
double interest = balance * (interestRate / 12);
balance += interest;
withdrawalCount = 0; // Reset monthly withdrawal count
}
}
}
// CheckingAccount.java
public class CheckingAccount extends Account {
private double overdraftLimit;
public CheckingAccount(String accountNumber, String holderName,
double initialBalance, double overdraftLimit) {
super(accountNumber, holderName, initialBalance);
this.overdraftLimit = overdraftLimit;
}
@Override
protected boolean canWithdraw(double amount) {
return (balance + overdraftLimit) >= amount;
}
}
// Transaction.java
public class Transaction {
private final String transactionId;
private final TransactionType type;
private final double amount;
private final double balanceAfter;
private final LocalDateTime timestamp;
public Transaction(TransactionType type, double amount, double balanceAfter) {
this.transactionId = UUID.randomUUID().toString();
this.type = type;
this.amount = amount;
this.balanceAfter = balanceAfter;
this.timestamp = LocalDateTime.now();
}
// Getters...
}
enum TransactionType {
DEPOSIT, WITHDRAWAL, TRANSFER_IN, TRANSFER_OUT, INTEREST
}
Bank Management System
// Bank.java
public class Bank {
private Map<String, Account> accounts;
private ExecutorService transactionExecutor;
private final ReentrantLock bankLock = new ReentrantLock();
public Bank() {
accounts = new ConcurrentHashMap<>();
transactionExecutor = Executors.newFixedThreadPool(10);
}
public void createSavingsAccount(String accountNumber, String holderName,
double initialBalance, double interestRate) {
Account account = new SavingsAccount(accountNumber, holderName,
initialBalance, interestRate);
accounts.put(accountNumber, account);
}
public void createCheckingAccount(String accountNumber, String holderName,
double initialBalance, double overdraftLimit) {
Account account = new CheckingAccount(accountNumber, holderName,
initialBalance, overdraftLimit);
accounts.put(accountNumber, account);
}
public CompletableFuture<Boolean> transfer(String fromAccount, String toAccount, double amount) {
return CompletableFuture.supplyAsync(() -> {
Account from = accounts.get(fromAccount);
Account to = accounts.get(toAccount);
if (from == null || to == null) {
throw new IllegalArgumentException("Invalid account number");
}
// Ensure consistent ordering to prevent deadlocks
Account firstLock = fromAccount.compareTo(toAccount) < 0 ? from : to;
Account secondLock = fromAccount.compareTo(toAccount) < 0 ? to : from;
synchronized(firstLock) {
synchronized(secondLock) {
if (from.getBalance() >= amount) {
from.withdraw(amount);
to.deposit(amount);
return true;
}
}
}
return false;
}, transactionExecutor);
}
public Account getAccount(String accountNumber) {
return accounts.get(accountNumber);
}
public List<Account> getAllAccounts() {
return new ArrayList<>(accounts.values());
}
public Map<String, Double> generateBalanceReport() {
return accounts.entrySet().stream()
.collect(Collectors.toMap(
Map.Entry::getKey,
entry -> entry.getValue().getBalance()
));
}
public void applyMonthlyInterest() {
accounts.values().parallelStream()
.filter(account -> account instanceof SavingsAccount)
.map(account -> (SavingsAccount) account)
.forEach(SavingsAccount::applyMonthlyInterest);
}
public void shutdown() {
transactionExecutor.shutdown();
try {
if (!transactionExecutor.awaitTermination(60, TimeUnit.SECONDS)) {
transactionExecutor.shutdownNow();
}
} catch (InterruptedException e) {
transactionExecutor.shutdownNow();
}
}
}
E-commerce Order Processing System
Product & Inventory
// Product.java
public class Product implements Serializable {
private String productId;
private String name;
private String description;
private double price;
private String category;
private int stockQuantity;
private Set<String> tags;
public Product(String productId, String name, String description,
double price, String category, int stockQuantity) {
this.productId = productId;
this.name = name;
this.description = description;
this.price = price;
this.category = category;
this.stockQuantity = stockQuantity;
this.tags = new HashSet<>();
}
public synchronized boolean reserveStock(int quantity) {
if (stockQuantity >= quantity) {
stockQuantity -= quantity;
return true;
}
return false;
}
public synchronized void restoreStock(int quantity) {
stockQuantity += quantity;
}
public boolean isInStock() {
return stockQuantity > 0;
}
// Getters and setters...
}
// ShoppingCart.java
public class ShoppingCart {
private Map<String, CartItem> items;
private String customerId;
public ShoppingCart(String customerId) {
this.customerId = customerId;
this.items = new HashMap<>();
}
public void addItem(Product product, int quantity) {
String productId = product.getProductId();
if (items.containsKey(productId)) {
CartItem existingItem = items.get(productId);
existingItem.setQuantity(existingItem.getQuantity() + quantity);
} else {
items.put(productId, new CartItem(product, quantity));
}
}
public void removeItem(String productId) {
items.remove(productId);
}
public double calculateTotal() {
return items.values().stream()
.mapToDouble(item -> item.getProduct().getPrice() * item.getQuantity())
.sum();
}
public Map<String, CartItem> getItems() {
return new HashMap<>(items);
}
public void clear() {
items.clear();
}
}
Order Processing
// Order.java
public class Order implements Serializable {
private String orderId;
private String customerId;
private List<OrderItem> items;
private OrderStatus status;
private LocalDateTime orderDate;
private double totalAmount;
private String shippingAddress;
public Order(String customerId, String shippingAddress) {
this.orderId = generateOrderId();
this.customerId = customerId;
this.shippingAddress = shippingAddress;
this.items = new ArrayList<>();
this.status = OrderStatus.PENDING;
this.orderDate = LocalDateTime.now();
this.totalAmount = 0.0;
}
public void addItem(Product product, int quantity) {
OrderItem item = new OrderItem(product, quantity, product.getPrice());
items.add(item);
calculateTotal();
}
private void calculateTotal() {
totalAmount = items.stream()
.mapToDouble(item -> item.getPrice() * item.getQuantity())
.sum();
}
public void updateStatus(OrderStatus newStatus) {
this.status = newStatus;
}
private String generateOrderId() {
return "ORD-" + System.currentTimeMillis() + "-" +
String.format("%04d", new Random().nextInt(10000));
}
// Getters...
}
enum OrderStatus {
PENDING, CONFIRMED, PROCESSING, SHIPPED, DELIVERED, CANCELLED
}
// OrderItem.java
public class OrderItem implements Serializable {
private Product product;
private int quantity;
private double price; // Price at time of order
public OrderItem(Product product, int quantity, double price) {
this.product = product;
this.quantity = quantity;
this.price = price;
}
public double getSubtotal() {
return price * quantity;
}
// Getters and setters...
}
Order Processing Service
// OrderProcessor.java
public class OrderProcessor {
private Map<String, Product> inventory;
private Map<String, Order> orders;
private Map<String, ShoppingCart> carts;
private Queue<String> processingQueue;
private ExecutorService orderProcessingPool;
private final Object inventoryLock = new Object();
public OrderProcessor() {
inventory = new ConcurrentHashMap<>();
orders = new ConcurrentHashMap<>();
carts = new ConcurrentHashMap<>();
processingQueue = new ConcurrentLinkedQueue<>();
orderProcessingPool = Executors.newFixedThreadPool(5);
// Start background order processing
startOrderProcessing();
}
public void addProduct(Product product) {
inventory.put(product.getProductId(), product);
}
public ShoppingCart getCart(String customerId) {
return carts.computeIfAbsent(customerId, k -> new ShoppingCart(customerId));
}
public boolean addToCart(String customerId, String productId, int quantity) {
Product product = inventory.get(productId);
if (product == null || !product.isInStock()) {
return false;
}
ShoppingCart cart = getCart(customerId);
cart.addItem(product, quantity);
return true;
}
public Order createOrder(String customerId, String shippingAddress) {
ShoppingCart cart = carts.get(customerId);
if (cart == null || cart.getItems().isEmpty()) {
throw new IllegalStateException("Cart is empty");
}
Order order = new Order(customerId, shippingAddress);
// Reserve inventory and create order items
synchronized(inventoryLock) {
for (CartItem cartItem : cart.getItems().values()) {
Product product = cartItem.getProduct();
int quantity = cartItem.getQuantity();
if (!product.reserveStock(quantity)) {
// Restore any previously reserved stock
rollbackOrderReservations(order);
throw new InsufficientStockException(
"Insufficient stock for product: " + product.getName());
}
order.addItem(product, quantity);
}
}
orders.put(order.getOrderId(), order);
cart.clear();
// Queue for processing
processingQueue.offer(order.getOrderId());
return order;
}
private void rollbackOrderReservations(Order order) {
for (OrderItem item : order.getItems()) {
item.getProduct().restoreStock(item.getQuantity());
}
}
private void startOrderProcessing() {
orderProcessingPool.submit(() -> {
while (!Thread.currentThread().isInterrupted()) {
try {
String orderId = processingQueue.poll();
if (orderId != null) {
processOrder(orderId);
}
Thread.sleep(1000); // Check every second
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
break;
}
}
});
}
private void processOrder(String orderId) {
Order order = orders.get(orderId);
if (order != null && order.getStatus() == OrderStatus.PENDING) {
try {
// Simulate payment processing
Thread.sleep(2000);
order.updateStatus(OrderStatus.CONFIRMED);
// Simulate order fulfillment
Thread.sleep(3000);
order.updateStatus(OrderStatus.PROCESSING);
// Simulate shipping
Thread.sleep(1000);
order.updateStatus(OrderStatus.SHIPPED);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
public List<Product> searchProducts(String searchTerm) {
return inventory.values().stream()
.filter(product ->
product.getName().toLowerCase().contains(searchTerm.toLowerCase()) ||
product.getDescription().toLowerCase().contains(searchTerm.toLowerCase()) ||
product.getTags().stream().anyMatch(tag ->
tag.toLowerCase().contains(searchTerm.toLowerCase())))
.collect(Collectors.toList());
}
public List<Product> getProductsByCategory(String category) {
return inventory.values().stream()
.filter(product -> product.getCategory().equalsIgnoreCase(category))
.collect(Collectors.toList());
}
public Map<String, Long> getOrderStatistics() {
return orders.values().stream()
.collect(Collectors.groupingBy(
order -> order.getStatus().toString(),
Collectors.counting()
));
}
public void shutdown() {
orderProcessingPool.shutdown();
}
}
class InsufficientStockException extends RuntimeException {
public InsufficientStockException(String message) {
super(message);
}
}
Main Application Demonstrations
Student Management Demo
public class StudentManagementDemo {
public static void main(String[] args) {
StudentManager manager = new StudentManager();
// Create courses
Course javaCourse = new Course("CS101", "Java Programming",
3, "Dr. Smith", 30);
Course dataStructures = new Course("CS201", "Data Structures",
4, "Dr. Johnson", 25);
manager.addCourse(javaCourse);
manager.addCourse(dataStructures);
// Create students
Student student1 = new Student("S001", "Alice Johnson",
"alice@email.com");
Student student2 = new Student("S002", "Bob Smith",
"bob@email.com");
Student student3 = new Student("S003", "Carol Davis",
"carol@email.com");
manager.addStudent(student1);
manager.addStudent(student2);
manager.addStudent(student3);
// Enroll students
manager.enrollStudent("S001", "CS101");
manager.enrollStudent("S001", "CS201");
manager.enrollStudent("S002", "CS101");
manager.enrollStudent("S003", "CS201");
// Record grades
manager.recordGrade("S001", "CS101", 3.7, 3); // A
manager.recordGrade("S001", "CS201", 3.3, 4); // A-
manager.recordGrade("S002", "CS101", 3.0, 3); // B+
manager.recordGrade("S003", "CS201", 4.0, 4); // A
// Display results
System.out.println("Top Students:");
List<Student> topStudents = manager.getTopStudents(3);
for (Student student : topStudents) {
System.out.printf("%s - GPA: %.2f%n",
student.getName(), student.calculateGPA());
}
// Course enrollment statistics
Map<String, Long> stats = manager.getCourseEnrollmentStats();
System.out.println("\nCourse Enrollment:");
stats.forEach((course, count) ->
System.out.printf("%s: %d students%n", course, count));
}
}
Banking System Demo
public class BankingDemo {
public static void main(String[] args) throws Exception {
Bank bank = new Bank();
// Create accounts
bank.createSavingsAccount("SAV001", "Alice Smith",
1000.0, 0.02);
bank.createCheckingAccount("CHK001", "Bob Johnson",
500.0, 200.0);
bank.createSavingsAccount("SAV002", "Carol Davis",
2000.0, 0.02);
// Perform transactions
Account aliceAccount = bank.getAccount("SAV001");
Account bobAccount = bank.getAccount("CHK001");
// Deposits and withdrawals
aliceAccount.deposit(500.0);
bobAccount.withdraw(100.0);
System.out.println("Initial Balances:");
System.out.printf("Alice: $%.2f%n", aliceAccount.getBalance());
System.out.printf("Bob: $%.2f%n", bobAccount.getBalance());
// Transfer money between accounts
CompletableFuture<Boolean> transferResult =
bank.transfer("SAV001", "CHK001", 300.0);
boolean success = transferResult.get();
System.out.println("\nTransfer successful: " + success);
System.out.println("After Transfer:");
System.out.printf("Alice: $%.2f%n", aliceAccount.getBalance());
System.out.printf("Bob: $%.2f%n", bobAccount.getBalance());
// Generate balance report
Map<String, Double> balanceReport = bank.generateBalanceReport();
System.out.println("\nBank Balance Report:");
balanceReport.forEach((account, balance) ->
System.out.printf("%s: $%.2f%n", account, balance));
// Transaction history
System.out.println("\nAlice's Transaction History:");
aliceAccount.getTransactionHistory().forEach(transaction ->
System.out.printf("%s: $%.2f (Balance: $%.2f) at %s%n",
transaction.getType(), transaction.getAmount(),
transaction.getBalanceAfter(), transaction.getTimestamp()));
bank.shutdown();
}
}
E-commerce System Demo
public class EcommerceDemo {
public static void main(String[] args) throws Exception {
OrderProcessor processor = new OrderProcessor();
// Add products to inventory
Product laptop = new Product("P001", "Gaming Laptop",
"High-performance gaming laptop", 1299.99, "Electronics", 10);
Product mouse = new Product("P002", "Wireless Mouse",
"Ergonomic wireless mouse", 29.99, "Electronics", 50);
Product keyboard = new Product("P003", "Mechanical Keyboard",
"RGB mechanical keyboard", 149.99, "Electronics", 25);
Product book = new Product("P004", "Java Programming Book",
"Comprehensive Java guide", 49.99, "Books", 30);
laptop.getTags().addAll(Arrays.asList("gaming", "laptop", "computer"));
mouse.getTags().addAll(Arrays.asList("mouse", "wireless", "peripheral"));
keyboard.getTags().addAll(Arrays.asList("keyboard", "mechanical", "rgb"));
book.getTags().addAll(Arrays.asList("java", "programming", "education"));
processor.addProduct(laptop);
processor.addProduct(mouse);
processor.addProduct(keyboard);
processor.addProduct(book);
// Customer shopping
String customerId = "CUST001";
// Add items to cart
processor.addToCart(customerId, "P001", 1); // Laptop
processor.addToCart(customerId, "P002", 2); // Mice
processor.addToCart(customerId, "P003", 1); // Keyboard
// Display cart
ShoppingCart cart = processor.getCart(customerId);
System.out.println("Shopping Cart:");
cart.getItems().forEach((productId, item) -> {
Product product = item.getProduct();
System.out.printf("%s x%d - $%.2f each = $%.2f%n",
product.getName(), item.getQuantity(),
product.getPrice(), product.getPrice() * item.getQuantity());
});
System.out.printf("Total: $%.2f%n", cart.calculateTotal());
// Create order
try {
Order order = processor.createOrder(customerId, "123 Main St, City, State");
System.out.println("\nOrder created: " + order.getOrderId());
System.out.println("Order status: " + order.getStatus());
System.out.printf("Order total: $%.2f%n", order.getTotalAmount());
// Wait for order processing
Thread.sleep(8000);
System.out.println("Final order status: " + order.getStatus());
} catch (InsufficientStockException e) {
System.err.println("Order failed: " + e.getMessage());
}
// Search functionality
System.out.println("\nSearch Results for 'gaming':");
List<Product> searchResults = processor.searchProducts("gaming");
searchResults.forEach(product ->
System.out.printf("%s - $%.2f (Stock: %d)%n",
product.getName(), product.getPrice(), product.getStockQuantity()));
// Category browsing
System.out.println("\nElectronics Category:");
List<Product> electronics = processor.getProductsByCategory("Electronics");
electronics.forEach(product ->
System.out.printf("%s - $%.2f%n", product.getName(), product.getPrice()));
// Order statistics
System.out.println("\nOrder Statistics:");
Map<String, Long> stats = processor.getOrderStatistics();
stats.forEach((status, count) ->
System.out.printf("%s: %d orders%n", status, count));
processor.shutdown();
}
}
Best Practices & Performance Optimization
Memory Management
Key Principles:
- Use appropriate collection types
- Implement proper equals() and hashCode()
- Close resources with try-with-resources
- Avoid memory leaks with listeners
// Efficient resource management
public class DataProcessor implements AutoCloseable {
private final List<String> data;
private final ExecutorService executor;
public DataProcessor() {
// Use ArrayList for indexed access
this.data = new ArrayList<>();
this.executor = Executors.newFixedThreadPool(4);
}
public void processLargeDataset(Path filePath) throws IOException {
// Use try-with-resources for automatic cleanup
try (BufferedReader reader = Files.newBufferedReader(filePath);
Stream<String> lines = reader.lines()) {
// Process in parallel for better performance
List<CompletableFuture<String>> futures = lines
.filter(line -> !line.trim().isEmpty())
.map(line -> CompletableFuture.supplyAsync(() ->
processLine(line), executor))
.collect(Collectors.toList());
// Collect results
for (CompletableFuture<String> future : futures) {
try {
data.add(future.get());
} catch (InterruptedException | ExecutionException e) {
// Handle errors appropriately
Thread.currentThread().interrupt();
throw new RuntimeException("Processing failed", e);
}
}
}
}
private String processLine(String line) {
// Simulate processing
return line.toUpperCase().trim();
}
@Override
public void close() {
executor.shutdown();
try {
if (!executor.awaitTermination(60, TimeUnit.SECONDS)) {
executor.shutdownNow();
}
} catch (InterruptedException e) {
executor.shutdownNow();
Thread.currentThread().interrupt();
}
}
}
Error Handling Strategies
Exception Handling Patterns:
- Use specific exception types
- Fail fast with validation
- Log errors appropriately
- Provide meaningful error messages
// Comprehensive error handling
public class UserService {
private static final Logger logger =
LoggerFactory.getLogger(UserService.class);
public User createUser(String email, String name, int age)
throws ValidationException, UserCreationException {
// Input validation with specific exceptions
validateUserInput(email, name, age);
try {
// Check if user already exists
if (userExists(email)) {
throw new UserCreationException(
"User with email " + email + " already exists");
}
User user = new User(email, name, age);
saveUser(user);
logger.info("Successfully created user: {}", email);
return user;
} catch (DatabaseException e) {
logger.error("Database error while creating user: {}", email, e);
throw new UserCreationException(
"Failed to create user due to database error", e);
} catch (Exception e) {
logger.error("Unexpected error while creating user: {}", email, e);
throw new UserCreationException(
"An unexpected error occurred", e);
}
}
private void validateUserInput(String email, String name, int age)
throws ValidationException {
List<String> errors = new ArrayList<>();
if (email == null || !isValidEmail(email)) {
errors.add("Invalid email format");
}
if (name == null || name.trim().isEmpty()) {
errors.add("Name cannot be empty");
}
if (age < 0 || age > 150) {
errors.add("Age must be between 0 and 150");
}
if (!errors.isEmpty()) {
throw new ValidationException(
"Validation failed: " + String.join(", ", errors));
}
}
// Retry mechanism for transient failures
public <T> T executeWithRetry(Supplier<T> operation, int maxRetries)
throws Exception {
Exception lastException = null;
for (int attempt = 1; attempt <= maxRetries; attempt++) {
try {
return operation.get();
} catch (TransientException e) {
lastException = e;
logger.warn("Attempt {} failed, retrying... Error: {}",
attempt, e.getMessage());
if (attempt < maxRetries) {
try {
Thread.sleep(1000 * attempt); // Exponential backoff
} catch (InterruptedException ie) {
Thread.currentThread().interrupt();
throw new RuntimeException("Interrupted during retry", ie);
}
}
}
}
throw new RuntimeException(
"Operation failed after " + maxRetries + " attempts", lastException);
}
}
Unit Testing Examples
JUnit Test Examples
// StudentTest.java
import org.junit.jupiter.api.*;
import static org.junit.jupiter.api.Assertions.*;
class StudentTest {
private Student student;
private Course javaCourse;
private Course mathCourse;
@BeforeEach
void setUp() {
student = new Student("S001", "John Doe", "john@email.com");
javaCourse = new Course("CS101", "Java Programming", 3, "Dr. Smith", 30);
mathCourse = new Course("MATH201", "Calculus", 4, "Dr. Johnson", 25);
}
@Test
@DisplayName("Should enroll student in course successfully")
void testEnrollInCourse() {
student.enrollInCourse(javaCourse);
assertTrue(student.getCourses().contains(javaCourse));
assertTrue(javaCourse.getEnrolledStudents().contains(student));
}
@Test
@DisplayName("Should prevent duplicate enrollment")
void testPreventDuplicateEnrollment() {
student.enrollInCourse(javaCourse);
student.enrollInCourse(javaCourse); // Attempt duplicate
assertEquals(1, student.getCourses().size());
assertEquals(1, javaCourse.getEnrolledStudents().size());
}
@Test
@DisplayName("Should calculate GPA correctly")
void testGPACalculation() {
student.addGrade("CS101", new Grade(3.7, 3)); // A = 3.7 * 3 = 11.1
student.addGrade("MATH201", new Grade(3.0, 4)); // B+ = 3.0 * 4 = 12.0
// Total points: 23.1, Total credits: 7
// Expected GPA: 23.1 / 7 = 3.3
assertEquals(3.3, student.calculateGPA(), 0.01);
}
@Test
@DisplayName("Should return 0 GPA when no grades")
void testZeroGPAWithNoGrades() {
assertEquals(0.0, student.calculateGPA());
}
@Test
@DisplayName("Should handle null course enrollment")
void testNullCourseEnrollment() {
assertThrows(NullPointerException.class, () -> {
student.enrollInCourse(null);
});
}
}
Bank Account Tests
// BankAccountTest.java
import org.junit.jupiter.api.*;
import static org.junit.jupiter.api.Assertions.*;
class BankAccountTest {
private SavingsAccount savingsAccount;
private CheckingAccount checkingAccount;
@BeforeEach
void setUp() {
savingsAccount = new SavingsAccount(
"SAV001", "Alice Smith", 1000.0, 0.02);
checkingAccount = new CheckingAccount(
"CHK001", "Bob Johnson", 500.0, 200.0);
}
@Test
@DisplayName("Should deposit money successfully")
void testSuccessfulDeposit() {
assertTrue(savingsAccount.deposit(500.0));
assertEquals(1500.0, savingsAccount.getBalance(), 0.01);
}
@Test
@DisplayName("Should reject negative deposit")
void testNegativeDeposit() {
assertThrows(IllegalArgumentException.class, () -> {
savingsAccount.deposit(-100.0);
});
}
@Test
@DisplayName("Should withdraw within balance")
void testValidWithdrawal() {
assertTrue(savingsAccount.withdraw(300.0));
assertEquals(700.0, savingsAccount.getBalance(), 0.01);
}
@Test
@DisplayName("Should reject withdrawal exceeding balance for savings")
void testExcessiveWithdrawalSavings() {
assertFalse(savingsAccount.withdraw(1500.0));
assertEquals(1000.0, savingsAccount.getBalance(), 0.01);
}
@Test
@DisplayName("Should allow overdraft for checking account")
void testOverdraftChecking() {
assertTrue(checkingAccount.withdraw(600.0)); // $500 + $200 overdraft = $700 available
assertEquals(-100.0, checkingAccount.getBalance(), 0.01);
}
@Test
@DisplayName("Should track transaction history")
void testTransactionHistory() {
savingsAccount.deposit(200.0);
savingsAccount.withdraw(150.0);
List<Transaction> history = savingsAccount.getTransactionHistory();
assertEquals(2, history.size());
Transaction lastTransaction = history.get(history.size() - 1);
assertEquals(TransactionType.WITHDRAWAL, lastTransaction.getType());
assertEquals(150.0, lastTransaction.getAmount(), 0.01);
}
@ParameterizedTest
@ValueSource(doubles = {0.0, -50.0, -1.0})
@DisplayName("Should reject invalid withdrawal amounts")
void testInvalidWithdrawalAmounts(double amount) {
assertThrows(IllegalArgumentException.class, () -> {
savingsAccount.withdraw(amount);
});
}
@Test
@DisplayName("Should apply monthly interest correctly")
void testMonthlyInterest() {
savingsAccount.applyMonthlyInterest();
// Expected: 1000 + (1000 * 0.02 / 12) = 1000 + 1.67 = 1001.67
assertEquals(1001.67, savingsAccount.getBalance(), 0.01);
}
}
Summary & Key Takeaways
Programming Concepts Applied
- Object-Oriented Design: Inheritance, polymorphism, encapsulation
- Collections Framework: Lists, Maps, Sets, Queues
- Exception Handling: Custom exceptions, try-with-resources
- Multithreading: ExecutorService, synchronization, CompletableFuture
- File I/O: Serialization, NIO, resource management
- Stream API: Filtering, mapping, collecting
- Generics: Type safety, wildcards
- Interfaces: Default methods, functional interfaces
Development Best Practices
- SOLID Principles: Single responsibility, dependency injection
- Design Patterns: Observer, Factory, Strategy
- Error Handling: Fail-fast validation, meaningful exceptions
- Performance: Efficient algorithms, proper synchronization
- Testing: Unit tests, parameterized tests, mocking
- Code Quality: Clean code, documentation, logging
- Concurrency: Thread safety, deadlock prevention
- Resource Management: AutoCloseable, proper cleanup
Real-World Application Architecture
These examples demonstrate how to build scalable, maintainable Java applications by:
- Separating concerns with proper layering (data, business logic, presentation)
- Using appropriate data structures for different use cases
- Implementing robust error handling and logging
- Applying concurrent programming for performance
- Writing comprehensive tests for reliability
- Following Java best practices and conventions
Java Programming Mastery
Complete Course Summary
Course Completion Checklist
- ✅ Java Fundamentals & Syntax
- ✅ Object-Oriented Programming
- ✅ Exception Handling & File I/O
- ✅ Collections Framework & Generics
- ✅ Multithreading & Concurrency
- ✅ Advanced Features & Best Practices
- ✅ Real-World Application Development
- ✅ Testing & Quality Assurance
Ready for Professional Java Development!
Continue learning: Spring Framework, Microservices, and Advanced Patterns

