// Java 基础对照示例(不依赖 Spring,只用 JDK):record、接口 + 构造器注入、Optional、Stream、异常、并发 // 运行(JDK 21+):java OrderDemo.java —— 单文件源码直接运行,不需要先 javac import java.math.BigDecimal; import java.util.List; import java.util.Map; import java.util.Optional; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.atomic.AtomicInteger; import java.util.stream.Collectors; public class OrderDemo { // record:不可变数据类,自动生成构造器、getter、equals/hashCode/toString(类似 Go struct / Python dataclass(frozen)) record Order(String id, String tenant, String status, BigDecimal amount) {} // 接口 + 实现:Spring 中会用 @Repository 标注,由容器创建并注入 interface OrderRepository { Optional findById(String id); List findByTenant(String tenant); } static class InMemoryOrderRepository implements OrderRepository { private final Map data = new ConcurrentHashMap<>(); InMemoryOrderRepository(List seed) { seed.forEach(o -> data.put(o.id(), o)); } public Optional findById(String id) { return Optional.ofNullable(data.get(id)); } public List findByTenant(String tenant) { return data.values().stream().filter(o -> o.tenant().equals(tenant)).toList(); } } static class NotFoundException extends RuntimeException { NotFoundException(String msg) { super(msg); } } // 构造器注入:Spring 推荐的方式(@Service),依赖是 final 的,测试时可以直接传入假实现 static class OrderService { private final OrderRepository repo; OrderService(OrderRepository repo) { this.repo = repo; } Order get(String tenant, String id) { return repo.findById(id) .filter(o -> o.tenant().equals(tenant)) // 租户隔离:别的租户的订单当作不存在 .orElseThrow(() -> new NotFoundException("订单不存在: " + id)); } Map sumByStatus(String tenant) { // Stream 分组汇总;金额用 BigDecimal,不用 double return repo.findByTenant(tenant).stream() .collect(Collectors.groupingBy(Order::status, Collectors.reducing(BigDecimal.ZERO, Order::amount, BigDecimal::add))); } } public static void main(String[] args) throws Exception { var repo = new InMemoryOrderRepository(List.of( new Order("A001", "t1", "paid", new BigDecimal("19.90")), new Order("A002", "t1", "paid", new BigDecimal("0.10")), new Order("A003", "t1", "refunded", new BigDecimal("5.00")), new Order("B001", "t2", "paid", new BigDecimal("99.00")))); var service = new OrderService(repo); check(service.get("t1", "A001").amount().equals(new BigDecimal("19.90")), "查询订单"); try { service.get("t1", "B001"); check(false, "跨租户应当查不到"); } catch (NotFoundException e) { System.out.println("跨租户查询被拒绝: " + e.getMessage()); } var sums = service.sumByStatus("t1"); check(sums.get("paid").equals(new BigDecimal("20.00")), "BigDecimal 精确求和"); System.out.println("t1 按状态汇总: " + new java.util.TreeMap<>(sums)); System.out.println("用 double 计算金额的问题: 0.1 + 0.2 = " + (0.1 + 0.2)); // 并发:虚拟线程(JDK 21 正式特性)+ 原子计数,类比 Go 的 goroutine var counter = new AtomicInteger(); try (ExecutorService pool = Executors.newVirtualThreadPerTaskExecutor()) { for (int i = 0; i < 1000; i++) pool.submit(counter::incrementAndGet); } // try-with-resources:等待全部任务完成 check(counter.get() == 1000, "虚拟线程并发计数"); System.out.println("1000 个虚拟线程计数结果: " + counter.get()); System.out.println("全部检查通过"); } static void check(boolean ok, String name) { if (!ok) throw new AssertionError("检查失败: " + name); } }