前言
如果你也是从 public static void main(string[] args) 和 system.out.println() 开始java生涯的,那也是java老油条了。在日常的业务开发中,我们每天都在写着增删改查的逻辑,有时候会觉得java有点笨重,语法有点啰嗦。
但其实,java在不断进化。从我们熟悉的java 8到现在的java 25,它多了很多实用的新特性和一些不为人知的老技巧。用好它们,不仅能让代码更简洁,还能在同事面前小小地秀一下。

下面就聊几个我自己在工作中觉得特别好用的技巧,看看你用过几个。
用枚举(enum)干点正事
很多人对枚举的印象还停留在定义一组常量,比如 male, female。但其实,枚举远比这强大,它甚至可以拥有自己的方法和实现,非常适合用来替代一堆 if-else 或者 switch 的策略逻辑。
举个例子,假设我们有不同的会员等级,需要计算折扣后的价格:
// 利用枚举实现不同会员的折扣策略
public enum membertype {
regular {
@override
public double applydiscount(double price) {
return price * 0.98; // 普通会员98折
}
},
vip {
@override
public double applydiscount(double price) {
return price * 0.9; // vip会员9折
}
},
premium {
@override
public double applydiscount(double price) {
return price * 0.8; // 高级会员8折
}
};
public abstract double applydiscount(double price);
}
// 使用起来非常清晰
public class pricecalculator {
public static void main(string[] args) {
double originalprice = 100.0;
double vipprice = membertype.vip.applydiscount(originalprice);
system.out.println("vip会员价:" + vipprice); // 输出:vip会员价:90.0
}
}这样写,每种会员的折扣逻辑都封装在自己的枚举实例里,代码清晰,扩展起来也方便。以后要加新的会员等级,只需要添加一个新的枚举实例就行,完全符合开闭原则。
用记录(record)告别样板代码
自从java 16引入了 record 类型,我写dto(数据传输对象)的幸福感直线上升。以前为了定义一个简单的数据载体,得手动写一堆的 getter, setter, equals(), hashcode() 和 tostring(),或者依赖lombok。
现在,一行代码就够了。
// 以前的写法
// public class user {
// private final string username;
// private final string email;
// // ... 一大堆 getter, equals, hashcode, tostring ...
// }
// 现在用record
public record userprofile(string username, string email) {}
// 使用
public class main {
public static void main(string[] args) {
userprofile user = new userprofile("dev_user", "user@example.com");
system.out.println(user.username()); // 直接调用,像方法一样
system.out.println(user); // 自带了很好的tostring()实现
}
}编译器会自动帮你生成所有必需的方法,代码瞬间清爽了很多。
类型安全的id,防止传错参数
在业务代码里,经常会用 long 或者 string 来表示各种id,比如 userid, orderid, productid。这样做的风险是,方法的参数很容易传混。
// 很容易写错的调用
public void processorder(long userid, long orderid) {
// ...
}
// 调用时可能不小心把两个id搞反
processorder(orderid, userid); // 编译器不会报错,但逻辑全错了那就可以利用 record (或者普通类) 来给id一层包装,增加类型安全性,让编译器在编码阶段就帮我们发现错误。
public record userid(long value) {}
public record orderid(long value) {}
public class orderservice {
public void processorder(userid userid, orderid orderid) {
system.out.println("处理用户 " + userid.value() + " 的订单 " + orderid.value());
}
public static void main(string[] args) {
orderservice service = new orderservice();
userid userid = new userid(1001l);
orderid orderid = new orderid(9527l);
service.processorder(userid, orderid); // 正确
// service.processorder(orderid, userid); // 这行代码会直接编译失败,安全!
}
}这个小改动能避免很多难以排查的线上问题。
用 stream api 告别 for 循环
从java 8开始,stream api 就已经是处理集合的标配了。如果还在用 for 循环和一堆 if 来做筛选和转换,那代码读起来会很费劲。stream api可以用一种更声明式、更流畅的方式来操作数据。
比如,我们要从一堆产品里,筛选出价格大于500的,然后取出它们的名字:
import java.util.list;
import java.util.stream.collectors;
public class streamdemo {
record product(string name, double price) {}
public static void main(string[] args) {
list<product> products = list.of(
new product("笔记本电脑", 5999.0),
new product("鼠标", 299.0),
new product("机械键盘", 799.0)
);
// 使用stream api
list<string> expensiveproductnames = products.stream()
.filter(p -> p.price() > 500.0) // 筛选价格
.map(product::name) // 提取名称
.collect(collectors.tolist()); // 收集成列表
system.out.println(expensiveproductnames); // 输出: [笔记本电脑, 机械键盘]
}
}链式调用,一气呵成,代码的意图一目了然。
用文本块(text blocks)优雅地写多行字符串
以前在java代码里拼接sql或者json字符串,简直是一场灾难,充满了 + 号和 \n 转义符,可读性极差。java 15引入的文本块(text blocks)彻底解决了这个问题。
看看对比:
public class textblockdemo {
public static void main(string[] args) {
// 以前的方式,又丑又容易出错
string oldjson = "{\n" +
" "name": "alice",\n" +
" "age": 30\n" +
"}";
// 现在用文本块,所见即所得
string newjson = """
{
"name": "alice",
"age": 30
}
""";
system.out.println(oldjson.equals(newjson)); // 输出: true
}
}用三个双引号 """ 包起来,字符串的格式就能完全保留,代码干净多了。
还在用!= null?试试optional
空指针异常(nullpointerexception)应该不少 java 开发者都很熟了。为了避免它,我们代码里堆满了 if (obj != null) 的判断。optional 的出现就是为了更优雅地处理可能为空的情况。
import java.util.optional;
public class userrepository {
// 模拟从数据库查找用户
public optional<string> findusernamebyid(long id) {
if (id == 1l) {
return optional.of("alice");
}
return optional.empty(); // 表示没找到
}
public static void main(string[] args) {
userrepository repo = new userrepository();
// 优雅地处理
repo.findusernamebyid(1l)
.ifpresentorelse(
name -> system.out.println("找到用户:" + name),
() -> system.out.println("用户不存在")
);
// 获取值,如果不存在则提供一个默认值
string username = repo.findusernamebyid(2l).orelse("默认用户");
system.out.println("查询id为2的用户:" + username);
}
}用 optional 不仅能让代码意图更明确(这个方法的返回值可能为空),还能通过链式调用写出更流畅的代码。
管理好java环境,才能玩转新特性
看到这里,你可能已经注意到,上面提到的不少特性都和java版本有关。比如 record 是java 16的,文本块是java 15的,ifpresentorelse 是java 9的。在实际工作中,我们经常会遇到这样的情况:
老项目a还在用稳定的java 8。
新项目b想尝试java 17的lts版本。
自己想学习一下最新的java 25。
在电脑上同时管理这么多java版本,配置环境变量,为不同项目切换jdk,挺让人破防的。每次切换环境,都要敲一堆命令,或者在ide里改来改去,很影响开发效率。
所以,这时候就需要servbay。
它本来是一个集成了php、node.js等环境的web开发工具,但我发现它对java的支持也做得特别好。最让我喜欢的一点是,它可以一键安装和管理多个java版本。我可以同时安装java 8、11、17、21等多个版本,它们之间完全隔离,互不干扰。

而且,我还可以为不同的项目指定使用不同的java版本。比如,可以设置项目a的运行环境就是java 8,项目b就是java 23。这样一来,在切换项目时,根本不用关心jdk版本的问题,servbay都帮你自动处理好了。
对于我们java开发者来说,这意味着可以把更多精力放在代码和技术本身,而不是被环境配置这些琐事消耗。
总结
java依然是一门生命力旺盛的语言。学习和使用这些技巧,可以让我们的代码质量更高,开发体验也更好。而借助像servbay这样的工具,又能帮我们轻松搞定复杂的环境管理问题,让我们能更专注于写出优秀的代码。
到此这篇关于多年java老手总结的几个神仙技巧的文章就介绍到这了,更多相关java神仙技巧内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
发表评论