Java最佳实践案例

wen java案例 3

Java最佳实践案例

代码组织与结构

包命名规范

// 好的实践:倒置域名 + 项目/模块名
package com.example.project.service;
package org.openapi.common.util;
// 避免:无意义或过于简单的包名
package util; // 不推荐
package test; // 不推荐

单一切责原则(SRP)

// ❌ 坏实践:一个类承担太多职责
public class UserManager {
    public void createUser() { /* ... */ }
    public void sendEmail() { /* ... */ }
    public void generateReport() { /* ... */ }
    public void validateData() { /* ... */ }
}
// ✅ 好实践:每个类专注于单一职责
public class UserService {
    public void createUser(User user) { /* ... */ }
}
public class EmailService {
    public void sendWelcomeEmail(User user) { /* ... */ }
}
public class ReportService {
    public Report generateUserReport(List<User> users) { /* ... */ }
}
public class UserValidator {
    public boolean isValid(User user) { /* ... */ }
}

异常处理最佳实践

使用具体异常类型

// ❌ 坏实践:捕获过于宽泛的异常
try {
    // some code
} catch (Exception e) {
    logger.error("Error occurred", e);
    throw new RuntimeException(e);
}
// ✅ 好实践:捕获具体异常
try {
    // 文件操作
    FileInputStream fis = new FileInputStream("file.txt");
} catch (FileNotFoundException e) {
    logger.error("File not found", e);
    throw new CustomFileNotFoundException("Configuration file missing", e);
} catch (IOException e) {
    logger.error("IO error", e);
    throw new CustomIOException("Failed to read file", e);
}

自定义异常

// ✅ 好实践:创建有意义的自定义异常
public class InsufficientBalanceException extends RuntimeException {
    private final String accountId;
    private final BigDecimal currentBalance;
    private final BigDecimal requiredAmount;
    public InsufficientBalanceException(String accountId, 
                                       BigDecimal currentBalance, 
                                       BigDecimal requiredAmount) {
        super(String.format("Account %s has insufficient balance. Required: %s, Current: %s",
                           accountId, requiredAmount, currentBalance));
        this.accountId = accountId;
        this.currentBalance = currentBalance;
        this.requiredAmount = requiredAmount;
    }
    // getters...
}

资源管理

Try-with-Resources

// ❌ 坏实践:手动管理资源
BufferedReader reader = null;
try {
    reader = new BufferedReader(new FileReader("file.txt"));
    String line = reader.readLine();
} catch (IOException e) {
    logger.error("Error reading file", e);
} finally {
    if (reader != null) {
        try {
            reader.close();
        } catch (IOException e) {
            logger.error("Error closing reader", e);
        }
    }
}
// ✅ 好实践:使用try-with-resources自动关闭
try (BufferedReader reader = new BufferedReader(new FileReader("file.txt"));
     FileWriter writer = new FileWriter("output.txt")) {
    String line;
    while ((line = reader.readLine()) != null) {
        writer.write(line);
        writer.write("\n");
    }
} catch (IOException e) {
    logger.error("Error processing file", e);
}

集合与泛型

使用泛型增强类型安全

// ❌ 坏实践:使用原始类型
List list = new ArrayList();
list.add("string");
list.add(123);
String item = (String) list.get(0); // 需要强制类型转换,可能导致ClassCastException
// ✅ 好实践:使用泛型
List<String> stringList = new ArrayList<>();
stringList.add("string");
// stringList.add(123); // 编译错误,类型安全
String item = stringList.get(0); // 无需强制类型转换
// 使用通配符提高灵活性
public void processList(List<? extends Number> numbers) {
    for (Number number : numbers) {
        System.out.println(number.doubleValue());
    }
}

不可变集合

// ✅ 好实践:使用不可变集合
import java.util.Collections;
import java.util.List;
public class Constants {
    public static final List<String> SUPPORTED_LANGUAGES = 
        Collections.unmodifiableList(Arrays.asList("en", "zh", "ja", "ko"));
    // Java 9+ 使用of方法
    public static final List<String> SUPPORTED_LANGUAGES_V2 = 
        List.of("en", "zh", "ja", "ko");
    public static final Map<String, String> COUNTRY_CODES = 
        Map.of(
            "US", "United States",
            "CN", "China",
            "JP", "Japan"
        );
}

并发编程

使用并发工具类

// ❌ 坏实践:使用synchronized在集合上
public class Counter {
    private final Map<String, Integer> countMap = new HashMap<>();
    public synchronized void increment(String key) {
        countMap.merge(key, 1, Integer::sum);
    }
}
// ✅ 好实践:使用ConcurrentHashMap
public class Counter {
    private final ConcurrentHashMap<String, AtomicInteger> countMap = new ConcurrentHashMap<>();
    public void increment(String key) {
        countMap.computeIfAbsent(key, k -> new AtomicInteger()).incrementAndGet();
    }
    public int getCount(String key) {
        return countMap.getOrDefault(key, new AtomicInteger()).get();
    }
}
// 使用ExecutorService管理线程池
public class TaskExecutor {
    private final ExecutorService executor = Executors.newFixedThreadPool(10);
    public Future<String> submitTask(Callable<String> task) {
        return executor.submit(task);
    }
    public void shutdown() {
        executor.shutdown();
        try {
            if (!executor.awaitTermination(60, TimeUnit.SECONDS)) {
                executor.shutdownNow();
            }
        } catch (InterruptedException e) {
            executor.shutdownNow();
            Thread.currentThread().interrupt();
        }
    }
}

避免线程安全问题

// ❌ 坏实践:SimpleDateFormat线程不安全
public class DateFormatter {
    private static final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
    public String format(Date date) {
        return dateFormat.format(date); // 多线程环境下可能出错
    }
}
// ✅ 好实践:使用线程安全的DateTimeFormatter
public class DateFormatter {
    private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ISO_LOCAL_DATE;
    public String format(LocalDate date) {
        return date.format(FORMATTER); // 线程安全
    }
}

性能优化

字符串操作优化

// ❌ 坏实践:频繁字符串拼接
String result = "";
for (int i = 0; i < 1000; i++) {
    result += "Item " + i + ", "; // 每次循环创建新String对象
}
// ✅ 好实践:使用StringBuilder
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 1000; i++) {
    sb.append("Item ").append(i).append(", ");
}
String result = sb.toString();

懒加载优化

// ✅ 好实践:使用懒加载模式
public class DataLoader {
    private volatile HeavyData heavyData;
    private final ReentrantLock lock = new ReentrantLock();
    public HeavyData getHeavyData() {
        // 双重检查锁定
        if (heavyData == null) {
            lock.lock();
            try {
                if (heavyData == null) {
                    heavyData = loadHeavyData(); // 耗时操作
                }
            } finally {
                lock.unlock();
            }
        }
        return heavyData;
    }
}

设计模式应用

工厂模式

// ✅ 好实践:使用工厂模式创建对象
public interface Notification {
    void send(String message);
}
public class EmailNotification implements Notification {
    @Override
    public void send(String message) {
        // 发送邮件
    }
}
public class SMSNotification implements Notification {
    @Override
    public void send(String message) {
        // 发送短信
    }
}
public class NotificationFactory {
    public static Notification createNotification(NotificationType type) {
        return switch (type) {
            case EMAIL -> new EmailNotification();
            case SMS -> new SMSNotification();
            default -> throw new IllegalArgumentException("Unknown notification type: " + type);
        };
    }
}
// 使用
Notification notification = NotificationFactory.createNotification(NotificationType.EMAIL);
notification.send("Your order has been confirmed!");

策略模式

// ✅ 好实践:使用策略模式处理不同支付方式
public interface PaymentStrategy {
    boolean pay(BigDecimal amount);
}
public class CreditCardPayment implements PaymentStrategy {
    @Override
    public boolean pay(BigDecimal amount) {
        // 信用卡支付逻辑
        return true;
    }
}
public class PayPalPayment implements PaymentStrategy {
    @Override
    public boolean pay(BigDecimal amount) {
        // PayPal支付逻辑
        return true;
    }
}
public class ShoppingCart {
    private final List<Item> items = new ArrayList<>();
    private PaymentStrategy paymentStrategy;
    public void setPaymentStrategy(PaymentStrategy strategy) {
        this.paymentStrategy = strategy;
    }
    public void checkout() {
        BigDecimal total = calculateTotal();
        if (paymentStrategy.pay(total)) {
            // 结账成功
        }
    }
}

测试最佳实践

单元测试示例

// ✅ 好实践:编写全面测试
public class CalculatorTest {
    @Test
    void testDivideWithPositiveNumbers() {
        Calculator calculator = new Calculator();
        assertEquals(5.0, calculator.divide(10, 2), 0.001);
    }
    @Test
    void testDivideByZero() {
        Calculator calculator = new Calculator();
        assertThrows(IllegalArgumentException.class, 
            () -> calculator.divide(10, 0),
            "Division by zero should throw exception");
    }
    @Test
    void testDivideWithNegativeNumbers() {
        Calculator calculator = new Calculator();
        assertEquals(-5.0, calculator.divide(-10, 2), 0.001);
    }
    @Test
    void testDivideWithLargeNumbers() {
        Calculator calculator = new Calculator();
        assertEquals(1.0, calculator.divide(1000000, 1000000), 0.001);
    }
}
// 使用Mockito进行依赖隔离
@ExtendWith(MockitoExtension.class)
public class OrderServiceTest {
    @Mock
    private PaymentService paymentService;
    @Mock
    private NotificationService notificationService;
    @InjectMocks
    private OrderService orderService;
    @Test
    void testPlaceOrderSuccessfully() {
        // 准备测试数据
        Order order = new Order("123", BigDecimal.valueOf(99.99));
        // 配置Mock行为
        when(paymentService.processPayment(any(Payment.class)))
            .thenReturn(true);
        // 执行测试
        OrderResult result = orderService.placeOrder(order);
        // 验证结果
        assertTrue(result.isSuccess());
        verify(notificationService).sendOrderConfirmation(order);
    }
}

代码风格与文档

使用Optional避免NullPointerException

// ❌ 坏实践:返回null
public User findUserById(Long id) {
    // ...
    return null; // 调用方需要检查null
}
// ✅ 好实践:返回Optional
public Optional<User> findUserById(Long id) {
    // ...
    return Optional.ofNullable(user);
}
// 使用示例
findUserById(123L)
    .ifPresentOrElse(
        user -> System.out.println("Found: " + user.getName()),
        () -> System.out.println("User not found")
    );

JavaDoc文档注释

/**
 * 订单处理服务,负责订单的创建、更新和取消操作。
 *
 * <p>该类是线程安全的,所有公共方法都支持并发调用。</p>
 *
 * @author Zhang San
 * @version 1.0
 * @since 2023-01-01
 */
public class OrderService {
    /**
     * 根据订单ID获取订单信息。
     *
     * @param orderId 订单唯一标识符,不能为null
     * @return 包含订单信息的Optional对象
     * @throws IllegalArgumentException 如果orderId为null
     * @throws OrderNotFoundException 如果订单不存在
     */
    public Optional<Order> getOrderById(@NonNull Long orderId) {
        // 实现代码
    }
}

日志最佳实践

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class PaymentProcessor {
    private static final Logger log = LoggerFactory.getLogger(PaymentProcessor.class);
    public void processPayment(Payment payment) {
        log.debug("Processing payment: {}", payment.getId());
        try {
            // 处理支付逻辑
            log.info("Payment {} processed successfully", payment.getId());
        } catch (PaymentException e) {
            log.error("Failed to process payment {}", payment.getId(), e);
            throw e; // 重新抛出异常,由上层处理
        }
    }
}

这些最佳实践案例涵盖了Java开发中常见的场景,遵循这些实践可以提高代码质量、可维护性和性能,最佳实践不是一成不变的规则,而是应该根据具体项目需求和团队约定进行调整。

Java最佳实践案例

抱歉,评论功能暂时关闭!