李锋镝的博客

  • 首页
  • 时间轴
  • 评论区显眼包🔥
  • 左邻右舍
  • 博友圈
  • 关于我
    • 关于我
    • 另一个网站
    • 我的导航站
    • 网站地图
    • 赞助
  • 留言
  • 🚇开往
Destiny
自是人生长恨水长东
  1. 首页
  2. 后端
  3. 正文

Java进阶实战:10个高效技巧+环境管理指南,让代码简洁又优雅

2025年12月12日 161点热度 1人点赞 0条评论

Java作为一门生命力旺盛的编程语言,从Java 8到最新的Java 25,持续迭代出大量实用特性。但很多开发者仍停留在传统写法,重复编写样板代码、被空指针困扰、手动切换JDK环境……其实,用好Java的隐藏技巧与新特性,不仅能让代码更简洁、安全,还能大幅提升开发效率。本文将分享10个实战性极强的Java进阶技巧,涵盖枚举进阶、数据载体优化、空安全处理等核心场景,同时附上多版本JDK管理方案,帮你彻底摆脱繁琐工作。

一、枚举(Enum):不止于常量,更是策略容器

多数开发者仅用枚举定义常量(如性别、状态),却忽略了它可承载业务逻辑的强大能力。枚举支持抽象方法、实现接口,能完美替代冗余的if-else/switch,让策略逻辑更清晰、扩展更灵活。

1. 枚举实现策略模式

以电商会员折扣为例,不同会员等级对应不同折扣规则,用枚举封装可直接调用,无需判断分支:

// 会员等级枚举(包含折扣策略)
public enum MemberGrade {
    // 普通会员:98折 + 无额外权益
    REGULAR(0.98) {
        @Override
        public double calculateFinalPrice(double originalPrice, int points) {
            // 普通会员无积分抵扣,直接按折扣计算
            return originalPrice * getDiscount();
        }

        @Override
        public String get权益Desc() {
            return "基础购物保障";
        }
    },
    // VIP会员:9折 + 100积分抵1元
    VIP(0.9) {
        @Override
        public double calculateFinalPrice(double originalPrice, int points) {
            // 积分抵扣上限为订单金额的30%
            double pointDeduction = Math.min(points / 100.0, originalPrice * 0.3);
            return (originalPrice - pointDeduction) * getDiscount();
        }

        @Override
        public String get权益Desc() {
            return "积分抵扣+专属客服";
        }
    },
    // 高级会员:8折 + 50积分抵1元 + 免运费
    PREMIUM(0.8) {
        @Override
        public double calculateFinalPrice(double originalPrice, int points) {
            double pointDeduction = Math.min(points / 50.0, originalPrice * 0.5);
            double discountedPrice = (originalPrice - pointDeduction) * getDiscount();
            // 高级会员订单金额≥100元免运费(假设运费10元)
            return discountedPrice >= 100 ? discountedPrice : discountedPrice + 10;
        }

        @Override
        public String get权益Desc() {
            return "积分多倍抵扣+免运费+优先发货";
        }
    };

    // 折扣率(成员变量)
    private final double discount;

    // 构造方法
    MemberGrade(double discount) {
        this.discount = discount;
    }

    // 获取折扣率(普通方法)
    public double getDiscount() {
        return discount;
    }

    // 抽象方法:计算最终价格(子类必须实现)
    public abstract double calculateFinalPrice(double originalPrice, int points);

    // 抽象方法:获取权益描述
    public abstract String get权益Desc();
}

// 调用示例
public class PriceCalculator {
    public static void main(String[] args) {
        double originalPrice = 200.0;
        int userPoints = 1500;

        // VIP会员价格计算
        double vipPrice = MemberGrade.VIP.calculateFinalPrice(originalPrice, userPoints);
        System.out.println("VIP会员最终价格:" + vipPrice); // 输出:(200 - 15) * 0.9 = 166.5
        System.out.println("VIP会员权益:" + MemberGrade.VIP.get权益Desc());

        // 高级会员价格计算
        double premiumPrice = MemberGrade.PREMIUM.calculateFinalPrice(originalPrice, userPoints);
        System.out.println("高级会员最终价格:" + premiumPrice); // 输出:(200 - 30) * 0.8 = 136.0(≥100免运费)
    }
}

2. 枚举的其他实用场景

  • 状态机管理:定义订单状态(待支付→已支付→已发货→已完成),枚举中封装状态流转规则,避免非法状态切换;
  • 枚举工厂:通过枚举静态方法创建对象,统一实例化入口,如PaymentType.ALIPAY.createPayment();
  • 枚举映射:枚举中添加fromCode()方法,实现编码与枚举的快速转换(如从数据库存储的1/2/3映射到REGULAR/VIP/PREMIUM)。

二、Record:告别样板代码,优雅定义数据载体

Java 16引入的Record类型,专为“数据载体”场景设计(如DTO、VO、查询结果封装)。它自动生成getter、equals()、hashCode()、toString()方法,一行代码替代数十行样板代码,且天然不可变,线程安全。

1. 基础用法:替代传统DTO

// 传统DTO(需手动写getter、equals等,或依赖Lombok)
// public class OrderDTO {
//     private final Long orderId;
//     private final String productName;
//     private final BigDecimal amount;
//     private final LocalDateTime createTime;
//
//     // 构造方法
//     public OrderDTO(Long orderId, String productName, BigDecimal amount, LocalDateTime createTime) {
//         this.orderId = orderId;
//         this.productName = productName;
//         this.amount = amount;
//         this.createTime = createTime;
//     }
//
//     // 一堆getter方法
//     public Long getOrderId() { return orderId; }
//     // ... 其他getter ...
//
//     // equals、hashCode、toString ...
// }

// Record实现(一行搞定,编译器自动生成所有方法)
public record OrderDTO(
    Long orderId,
    String productName,
    BigDecimal amount,
    LocalDateTime createTime
) {}

// 使用示例
public class RecordDemo {
    public static void main(String[] args) {
        OrderDTO order = new OrderDTO(
            9527L,
            "机械键盘",
            new BigDecimal("799.00"),
            LocalDateTime.of(2025, 10, 24, 14, 30)
        );

        // 直接调用属性名对应的方法(无get前缀)
        System.out.println("订单ID:" + order.orderId());
        System.out.println("订单信息:" + order); // 自动生成的toString(),格式清晰
        // 输出:OrderDTO[orderId=9527, productName=机械键盘, amount=799.00, createTime=2025-10-24T14:30]

        // 天然支持equals比较(基于所有属性)
        OrderDTO order2 = new OrderDTO(9527L, "机械键盘", new BigDecimal("799.00"), LocalDateTime.of(2025, 10, 24, 14, 30));
        System.out.println(order.equals(order2)); // 输出:true
    }
}

2. Record进阶:验证与扩展

Record虽不可变,但可通过构造方法增强数据校验,或添加静态方法扩展功能:

public record UserVO(String username, String email, Integer age) {
    // 自定义构造方法(用于数据校验)
    public UserVO {
        // 校验用户名非空且长度≥3
        if (username == null || username.length() < 3) {
            throw new IllegalArgumentException("用户名长度不能小于3位");
        }
        // 校验邮箱格式
        if (email == null || !email.contains("@")) {
            throw new IllegalArgumentException("邮箱格式无效");
        }
        // 校验年龄合理范围
        if (age != null && (age < 0 || age > 150)) {
            throw new IllegalArgumentException("年龄范围无效");
        }
    }

    // 静态方法:创建默认用户(工厂模式)
    public static UserVO createDefaultUser(String username) {
        return new UserVO(username, username + "@default.com", 18);
    }

    // 扩展方法:获取邮箱域名
    public String getEmailDomain() {
        return email.split("@")[1];
    }
}

// 测试
public class RecordAdvanced {
    public static void main(String[] args) {
        UserVO defaultUser = UserVO.createDefaultUser("dev_john");
        System.out.println("默认用户邮箱域名:" + defaultUser.getEmailDomain()); // 输出:default.com

        // 非法参数会抛出异常
        // UserVO invalidUser = new UserVO("jo", "invalid-email", 200);
        // 抛出:IllegalArgumentException: 用户名长度不能小于3位
    }
}

三、类型安全ID:从根源避免参数传错

业务开发中,Long/String常被用来表示各类ID(userId、orderId、productId),极易出现参数顺序传错的问题(如processOrder(orderId, userId)),编译器无法识别,线上排查困难。用Record或普通类包装ID,可实现类型安全,编译阶段即可规避错误。

1. 类型安全ID实现

// 用户ID包装类(Record实现,不可变)
public record UserId(Long value) {
    // 构造方法校验:ID非负
    public UserId {
        if (value == null || value < 0) {
            throw new IllegalArgumentException("用户ID不能为负");
        }
    }

    // 静态工厂方法:简化创建
    public static UserId of(Long value) {
        return new UserId(value);
    }
}

// 订单ID包装类
public record OrderId(Long value) {
    public OrderId {
        if (value == null || value < 1000) {
            throw new IllegalArgumentException("订单ID无效");
        }
    }

    public static OrderId of(Long value) {
        return new OrderId(value);
    }
}

// 服务类(参数类型明确)
public class OrderService {
    // 方法参数为类型化ID,无法传错
    public void processOrder(UserId userId, OrderId orderId) {
        System.out.printf("处理用户[%d]的订单[%d]%n", userId.value(), orderId.value());
    }

    public static void main(String[] args) {
        OrderService service = new OrderService();
        UserId userId = UserId.of(1001L);
        OrderId orderId = OrderId.of(9527L);

        service.processOrder(userId, orderId); // 正确调用,编译通过

        // 以下代码编译直接失败,从根源避免传错
        // service.processOrder(orderId, userId); 
        // 错误提示:The method processOrder(UserId, OrderId) in the type OrderService is not applicable for the arguments (OrderId, UserId)
    }
}

2. 优势与扩展

  • 编译时校验:不同类型ID无法混用,参数顺序错误直接编译失败;
  • 数据校验:构造方法中可添加ID合法性校验(如非负、格式正确);
  • 序列化友好:Record自动实现Serializable,可直接用于RPC调用或数据库映射;
  • 兼容框架:MyBatis、JPA等框架支持自定义类型转换器,可直接将数据库字段映射为类型化ID。

四、Stream API:替代for循环,实现声明式数据处理

Java 8引入的Stream API,以声明式、链式调用的方式处理集合,替代繁琐的for循环+if判断,代码更简洁、意图更清晰。它支持筛选、映射、聚合、排序等操作,还可结合Lambda表达式大幅提升开发效率。

1. 核心场景实战

场景1:筛选+映射+收集

从产品列表中筛选价格>500元的商品,提取名称并排序:

import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

// 产品Record
record Product(String name, double price, String category) {}

public class StreamBasic {
    public static void main(String[] args) {
        List<Product> products = List.of(
            new Product("笔记本电脑", 5999.0, "电子设备"),
            new Product("鼠标", 299.0, "电子配件"),
            new Product("机械键盘", 799.0, "电子配件"),
            new Product("打印机", 1299.0, "办公设备"),
            new Product("U盘", 129.0, "电子配件")
        );

        // 筛选价格>500元的商品 → 提取名称 → 按价格升序排序 → 收集为列表
        List<String> highPriceProductNames = products.stream()
                .filter(p -> p.price() > 500.0) // 筛选条件
                .sorted(Comparator.comparingDouble(Product::price)) // 按价格升序
                .map(Product::name) // 提取商品名称
                .collect(Collectors.toList()); // 收集结果

        System.out.println("高价商品列表:" + highPriceProductNames);
        // 输出:[机械键盘, 打印机, 笔记本电脑]
    }
}

场景2:分组统计

按商品分类分组,统计每组商品数量与平均价格:

import java.util.Map;
import java.util.stream.Collectors;

public class StreamGroup {
    public static void main(String[] args) {
        List<Product> products = List.of(
            new Product("笔记本电脑", 5999.0, "电子设备"),
            new Product("鼠标", 299.0, "电子配件"),
            new Product("机械键盘", 799.0, "电子配件"),
            new Product("打印机", 1299.0, "办公设备"),
            new Product("U盘", 129.0, "电子配件")
        );

        // 按分类分组 → 统计每组数量与平均价格
        Map<String, Map<String, Object>> categoryStats = products.stream()
                .collect(Collectors.groupingBy(
                    Product::category, // 分组键:商品分类
                    Collectors.of(
                        // 初始化统计容器(数量+总价格)
                        () -> Map.of("count", 0L, "totalPrice", 0.0),
                        // 累加逻辑
                        (stats, product) -> {
                            stats.put("count", (Long) stats.get("count") + 1);
                            stats.put("totalPrice", (Double) stats.get("totalPrice") + product.price());
                        },
                        // 合并多个分区的统计结果(并行流时使用)
                        (stats1, stats2) -> {
                            stats1.put("count", (Long) stats1.get("count") + (Long) stats2.get("count"));
                            stats1.put("totalPrice", (Double) stats1.get("totalPrice") + (Double) stats2.get("totalPrice"));
                            return stats1;
                        },
                        // 最终转换:计算平均价格
                        stats -> {
                            Long count = (Long) stats.get("count");
                            Double totalPrice = (Double) stats.get("totalPrice");
                            return Map.of(
                                "商品数量", count,
                                "平均价格", Math.round(totalPrice / count * 100) / 100.0 // 保留两位小数
                            );
                        }
                    )
                ));

        System.out.println("分类统计结果:" + categoryStats);
        // 输出:
        // {
        //   电子设备={商品数量=1, 平均价格=5999.0},
        //   电子配件={商品数量=3, 平均价格=409.0},
        //   办公设备={商品数量=1, 平均价格=1299.0}
        // }
    }
}

场景3:并行流提升性能

处理超大集合时,使用并行流(parallelStream())可利用多核CPU提升效率(注意线程安全问题):

// 并行流统计超大列表中偶数的总和
List<Long> bigList = List.of(1L, 2L, 3L, ...); // 假设百万级数据
long evenSum = bigList.parallelStream()
        .filter(n -> n % 2 == 0)
        .mapToLong(Long::longValue)
        .sum();

3. Stream API使用注意事项

  • 避免在Stream中修改外部变量(线程不安全),优先使用collect收集结果;
  • 并行流适合无状态、CPU密集型任务,IO密集型任务(如数据库查询)不适合;
  • 复杂业务逻辑可拆分为多个简单Stream操作,或使用peek()调试中间结果。

五、文本块(Text Blocks):优雅处理多行字符串

Java 15引入的文本块(Text Blocks),彻底解决了多行字符串拼接的痛点。用三个双引号"""包裹,无需手动添加+和\n,字符串格式完全保留,可读性大幅提升,尤其适合SQL、JSON、HTML等场景。

1. 基础用法:替代传统拼接

public class TextBlockDemo {
    public static void main(String[] args) {
        // 传统写法:繁琐且易出错
        String oldSql = "SELECT order_id, product_name, amount " +
                        "FROM t_order " +
                        "WHERE create_time >= '2025-01-01' " +
                        "  AND status = 'PAID' " +
                        "ORDER BY create_time DESC";

        // 文本块写法:所见即所得
        String newSql = """
            SELECT order_id, product_name, amount
            FROM t_order
            WHERE create_time >= '2025-01-01'
              AND status = 'PAID'
            ORDER BY create_time DESC
            """;

        System.out.println(oldSql.equals(newSql)); // 输出:true

        // JSON字符串示例
        String userJson = """
            {
              "userId": 1001,
              "username": "dev_john",
              "email": "john@example.com",
              "roles": ["USER", "ADMIN"],
              "address": {
                "city": "Beijing",
                "street": "Main Street"
              }
            }
            """;
        System.out.println(userJson);
    }
}

2. 进阶特性:格式化与转义

文本块支持formatted()方法动态填充参数,且可直接使用转义字符:

public class TextBlockAdvanced {
    public static void main(String[] args) {
        String userName = "Alice";
        int age = 30;
        String city = "Shanghai";

        // 动态格式化文本块
        String userProfile = """
            姓名:%s
            年龄:%d
            城市:%s
            注册时间:%s
            """.formatted(userName, age, city, LocalDate.now());

        System.out.println(userProfile);
        // 输出:
        // 姓名:Alice
        // 年龄:30
        // 城市:Shanghai
        // 注册时间:2025-10-24

        // 转义字符使用(如制表符\t、换行符\n)
        String formattedText = """
            序号\t姓名\t年龄
            1\tAlice\t30
            2\tBob\t25
            """;
        System.out.println(formattedText);
    }
}

六、Optional:优雅处理空指针,告别!= null

空指针异常(NullPointerException)是Java开发的常见痛点,传统if (obj != null)判断繁琐且冗余。Java 8引入的Optional类,通过容器化方式处理可能为空的值,支持链式调用,让空安全处理更优雅、意图更明确。

1. 核心用法:替代空判断

import java.util.Optional;

// 用户实体
record User(Long id, String name, String email) {}

// 用户仓库(模拟数据库查询)
class UserRepository {
    // 模拟查询:ID=1返回用户,否则返回null
    public User findUserById(Long id) {
        if (id == 1L) {
            return new User(1L, "Alice", "alice@example.com");
        }
        return null;
    }
}

public class OptionalBasic {
    public static void main(String[] args) {
        UserRepository repo = new UserRepository();

        // 传统写法:多层空判断(繁琐)
        User user = repo.findUserById(2L);
        if (user != null) {
            String email = user.email();
            if (email != null) {
                System.out.println("用户邮箱:" + email);
            } else {
                System.out.println("用户邮箱为空");
            }
        } else {
            System.out.println("用户不存在");
        }

        // Optional写法:链式调用(优雅)
        Optional.ofNullable(repo.findUserById(2L)) // 包装可能为null的对象
                .map(User::email) // 提取邮箱(若用户为null则跳过)
                .ifPresentOrElse(
                    email -> System.out.println("用户邮箱:" + email), // 邮箱存在时执行
                    () -> System.out.println("用户不存在或邮箱为空") // 邮箱为空时执行
                );

        // 获取值+默认值(用户不存在时返回默认用户)
        User defaultUser = Optional.ofNullable(repo.findUserById(2L))
                .orElse(new User(0L, "默认用户", "default@example.com"));
        System.out.println("最终用户:" + defaultUser);
    }
}

2. Optional进阶:过滤与转换

public class OptionalAdvanced {
    public static void main(String[] args) {
        UserRepository repo = new UserRepository();

        // 过滤+转换:查找ID=1的用户,且邮箱包含"example.com",提取用户名
        String validUserName = Optional.ofNullable(repo.findUserById(1L))
                .filter(u -> u.email() != null && u.email().contains("example.com")) // 过滤条件
                .map(User::name) // 提取用户名
                .orElse("无效用户");
        System.out.println("有效用户名:" + validUserName); // 输出:Alice

        // 抛出异常(用户不存在时抛出自定义异常)
        User requiredUser = Optional.ofNullable(repo.findUserById(3L))
                .orElseThrow(() -> new IllegalArgumentException("用户ID=3不存在"));
    }
}

3. 避坑指南

  • 不要用Optional.get()直接获取值(为空时抛出异常),优先使用orElse()/ifPresent();
  • 避免嵌套Optional(如Optional<Optional<User>>),可用flatMap()扁平化处理;
  • 方法返回值为Optional时,需在文档中说明“可能为空”,让调用方明确处理。

七、其他高效技巧:提升代码质量与效率

1. try-with-resources:自动关闭资源

替代手动关闭流、连接等资源,避免资源泄露,代码更简洁:

import java.io.BufferedReader;
import java.io.FileReader;

public class TryWithResourcesDemo {
    public static void main(String[] args) {
        // 传统写法:需手动关闭BufferedReader(易遗漏)
        BufferedReader reader = null;
        try {
            reader = new BufferedReader(new FileReader("data.txt"));
            String line = reader.readLine();
            System.out.println("读取内容:" + line);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (reader != null) {
                try {
                    reader.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }

        // try-with-resources写法:自动关闭资源(实现AutoCloseable接口的类均可)
        try (BufferedReader br = new BufferedReader(new FileReader("data.txt"))) {
            String line = br.readLine();
            System.out.println("读取内容:" + line);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

2. 接口默认方法:实现接口无侵入扩展

Java 8允许接口添加default方法,无需修改实现类即可扩展功能,兼容旧代码:

// 基础接口
interface Shape {
    double getArea(); // 抽象方法

    // 默认方法:计算周长(无需实现类重写)
    default double getPerimeter() {
        return 0.0; // 默认返回0,子类可覆盖
    }
}

// 圆形实现类
class Circle implements Shape {
    private final double radius;

    public Circle(double radius) {
        this.radius = radius;
    }

    @Override
    public double getArea() {
        return Math.PI * radius * radius;
    }

    // 覆盖默认方法:计算圆形周长
    @Override
    public double getPerimeter() {
        return 2 * Math.PI * radius;
    }
}

// 正方形实现类(无需实现getPerimeter(),使用默认方法)
class Square implements Shape {
    private final double side;

    public Square(double side) {
        this.side = side;
    }

    @Override
    public double getArea() {
        return side * side;
    }
}

3. 局部变量类型推断(var):简化代码

Java 10引入的var关键字,可自动推断局部变量类型,减少重复类型声明,代码更简洁(不影响可读性):

public class VarDemo {
    public static void main(String[] args) {
        // 传统写法:重复声明类型
        List<String> names = List.of("Alice", "Bob", "Charlie");
        Map<String, Integer> scoreMap = new HashMap<>();

        // var写法:自动推断类型
        var namesList = List.of("Alice", "Bob", "Charlie"); // 推断为List<String>
        var scoreMap2 = new HashMap<String, Integer>(); // 推断为HashMap<String, Integer>

        // 增强for循环中使用
        for (var name : namesList) {
            System.out.println(name);
        }

        // Stream流中使用
        var totalScore = scoreMap2.entrySet().stream()
                .mapToInt(Map.Entry::getValue)
                .sum();
    }
}

4. 密封类(Sealed Classes):限制继承

Java 17引入的密封类,可精确控制哪些类能继承它,避免无限制扩展导致的逻辑混乱,常用于枚举替代场景:

// 密封类:仅允许指定类继承
public sealed class PaymentMethod permits Alipay, WechatPay, CreditCard {
    public abstract boolean pay(BigDecimal amount);
}

// 允许继承的子类
final class Alipay extends PaymentMethod {
    @Override
    public boolean pay(BigDecimal amount) {
        System.out.println("支付宝支付:" + amount);
        return true;
    }
}

final class WechatPay extends PaymentMethod {
    @Override
    public boolean pay(BigDecimal amount) {
        System.out.println("微信支付:" + amount);
        return true;
    }
}

final class CreditCard extends PaymentMethod {
    @Override
    public boolean pay(BigDecimal amount) {
        System.out.println("信用卡支付:" + amount);
        return true;
    }
}

// 以下类无法继承PaymentMethod(编译失败)
// class ApplePay extends PaymentMethod { ... }

八、多版本JDK管理:用工具告别手动切换

Java版本迭代快,实际开发中常需同时维护多个项目:老项目用Java 8,新项目尝试Java 17,学习用Java 25。手动配置环境变量、切换JDK版本繁琐且易出错,借助工具可实现一键管理。

1. 工具选型:ServBay

ServBay是一款集成多语言环境的开发工具,对Java支持尤为友好,核心优势:

  • 一键安装多版本JDK:支持Java 8、11、17、21、25等版本,自动处理依赖,无需手动下载配置;
  • 环境隔离:多个JDK版本独立存储,互不干扰,避免版本冲突;
  • 项目级版本指定:可为不同项目绑定专属JDK版本(如项目A用Java 8,项目B用Java 17),切换项目时自动生效;
  • 可视化管理:图形化界面操作,无需记忆命令行,启停、切换版本只需点击。

2. 其他备选工具

  • SDKMAN!:命令行工具,支持Java、Kotlin等多语言版本管理,适合终端爱好者;
  • jEnv:轻量级Java版本管理工具,通过配置文件指定项目JDK版本;
  • IDE内置管理:IntelliJ IDEA、Eclipse等IDE支持在项目设置中直接切换JDK版本,适合单一IDE开发场景。

九、总结:Java进阶的核心逻辑

Java的进阶之路,本质是“用新特性替代繁琐写法,用工具解放重复劳动”:

  • 枚举与Record让代码更简洁、安全,减少样板代码;
  • Stream API与Optional让数据处理更优雅,规避空指针;
  • 文本块、var等特性提升编码效率,降低出错率;
  • 多版本管理工具让开发者聚焦业务,无需被环境配置困扰。

这些技巧并非孤立存在,实际开发中可灵活组合(如Record+Stream+Optional),形成高效的编码范式。随着Java持续迭代,建议保持学习新特性的习惯,同时结合工具提升效率,让代码既简洁优雅,又能快速落地业务。

除非注明,否则均为李锋镝的博客原创文章,转载必须以链接形式标明本文链接

本文链接:https://www.lifengdi.com/hou-duan/4641

相关文章

  • JDK 25 LTS 深度解析:18 项特性如何重塑 Java 开发体验
  • 数据库更新如何实现乐观锁
  • try...catch性能深度剖析:从JVM原理到实战优化,打破技术迷思
  • Spring WebFlux深度解析:异步非阻塞架构与实战落地指南
  • 重构 Controller 终极指南:从臃肿到优雅的 7 大黄金法则 + 实战技巧
本作品采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可
标签: JAVA JDK Record
最后更新:2025年12月12日

李锋镝

既然选择了远方,便只顾风雨兼程。

打赏 点赞
< 上一篇
下一篇 >

文章评论

1 2 3 4 5 6 7 8 9 11 12 13 14 15 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 46 47 48 49 50 51 52 53 54 55 57 58 60 61 62 63 64 65 66 67 69 72 74 76 77 78 79 80 81 82 85 86 87 90 92 93 94 95 96 97 98 99
取消回复

寻寻觅觅,冷冷清清,凄凄惨惨戚戚。乍暖还寒时候,最难将息。三杯两盏淡酒,怎敌他、晚来风急!雁过也,正伤心,却是旧时相识。
满地黄花堆积,憔悴损,如今有谁堪摘?守着窗儿,独自怎生得黑!梧桐更兼细雨,到黄昏、点点滴滴。这次第,怎一个愁字了得!

那年今日(01月25日)

  • 1979年:中国左翼文学运动开创者之一郑伯奇逝世
  • 1949年:日本帝国时期的政治家牧野伸显逝世
  • 1924年:第一届奥林匹克冬季运动会在夏蒙尼开幕
  • 1911年:中国第一部专门刑法典颁布
  • 1504年:意大利艺术家米开朗基罗完成大卫雕像
  • 更多历史事件
最新 热点 随机
最新 热点 随机
AI时代,个人技术博客的出路在哪里? 什么是Meta Server? 千万级大表新增字段实战指南:告别锁表与业务中断 在 SQL 中做范围查询时,使用 BETWEEN AND 和直接用 >/=/ 深度解析 Disruptor:无锁队列的高性能实现与实践 精通Linux根目录:核心文件夹深度解析与实战指南
玩博客的人是不是越来越少了?准备入手个亚太的ECS,友友们有什么建议吗?AI时代,个人技术博客的出路在哪里?使用WireGuard在Ubuntu 24.04系统搭建VPNWordPress实现用户评论等级排行榜插件WordPress网站换了个字体,差点儿把样式换崩了
基于Java8的Either类 居家办公了~ 祝大家六一儿童节快乐~~~ IntelliJ IDEA 2020.3.x永久白嫖(Windows/Mac) 看病难~取药难~~ 睡觉睡不踏实
标签聚合
WordPress K8s 分布式 AI编程 多线程 设计模式 JAVA ElasticSearch Redis SpringBoot JVM SQL AI docker IDEA 架构 MySQL 日常 数据库 Spring
友情链接
  • Blogs·CN
  • Honesty
  • Mr.Sun的博客
  • 临窗旋墨
  • 哥斯拉
  • 彬红茶日记
  • 志文工作室
  • 懋和道人
  • 搬砖日记
  • 旧时繁华
  • 林羽凡
  • 瓦匠个人小站
  • 皮皮社
  • 知向前端
  • 蜗牛工作室
  • 韩小韩博客
  • 风渡言

COPYRIGHT © 2026 lifengdi.com. ALL RIGHTS RESERVED.

域名年龄

Theme Kratos Made By Dylan

津ICP备2024022503号-3

京公网安备11011502039375号