Java足够严谨,但是不够简洁,想要把Java代码写的优雅,不要写费代码,不要拖沓。看案例
案例1(适当使用三目运算)
// Dubbo 源码,URL构造方法
public URL(String protocol, String username, String password, String host, int port, String path, Map<String, String> parameters) {
if ((username == null || username.length() == 0)
&& password != null && password.length() > 0) {
throw new IllegalArgumentException("Invalid url, password without username!");
}
this.protocol = protocol;
this.username = username;
this.password = password;
this.host = host;
this.port = (port < 0 ? 0 : port); // 比大小没必要这么写
// trim the beginning "/"
while (path != null && path.startsWith("/")) {
path = path.substring(1);
}
this.path = path;
// 下面对parameters的判断处理过程有点累赘
if (parameters == null) {
parameters = new HashMap<String, String>();
} else {
parameters = new HashMap<String, String>(parameters);
}
this.parameters = Collections.unmodifiableMap(parameters);
}
// 重构后
public URL(String protocol, String username, String password, String host, int port, String path, Map<String, String> parameters) {
if ((username == null || username.length() == 0) && password != null && password.length() > 0) {
throw new IllegalArgumentException("Invalid url, password without username!");
}
this.protocol = protocol;
this.username = username;
this.password = password;
this.host = host;
this.port = Math.max(port, 0);// 比大小,这么写更加清晰
this.parameters = Collections.unmodifiableMap(parameters == null ? new HashMap<>() : new HashMap<>(parameters));// 这边用三目运算符可以减少5行代码,而且也不难理解
while (path != null && path.startsWith("/")) {
path = path.substring(1);
}
this.path = path;
}
案例2(Map.computeIfAbsent挺好用的)
// Dubbo 源码,AbstractRegistry.subscribe(方法中的代码片段)
public void subscribe(URL url, NotifyListener listener) {
// ---------------------省略一些代码------------------------
Set<NotifyListener> listeners = subscribed.get(url);
if (listeners == null) {
subscribed.putIfAbsent(url, new ConcurrentHashSet<NotifyListener>());
listeners = subscribed.get(url);
}
listeners.add(listener);
}
// 重构后
public void subscribe(URL url, NotifyListener listener) {
// 利用computeIfAbsent,只有当key不存在时,后续的表达式才会被执行。不会影响性能
// 其次得到的必然是最新的值。多写几次会比较适应这样的写法
subscribed.computeIfAbsent(url, key -> new ConcurrentHashSet<>()).add(listener);
}
案例3
// Dubbo 源码,NettyClient.doOpen(方法中的代码片段)
// 问题1:getTimeout()如果大于3000,这个方法就会被调用2次。
// 问题2:用Math.max(3000, getTimeout())就能解决,if判断没有意义
protected void doOpen() throws Throwable {
// ---------------------省略一些代码------------------------
if (getTimeout() < 3000) {
bootstrap.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 3000);
} else {
bootstrap.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, getTimeout());
}
// ---------------------省略一些代码------------------------
}
// 重构后
protected void doOpen() throws Throwable {
// 使用Math.max(3000, getTimeout())就能变成一行代码。
bootstrap.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, Math.max(3000, getTimeout()));
}
案例4
// Dubbo 源码,Decodeable
// 从Dubbo的源码中不小心找到的,其他所有的接口声明都没有这问题,应该是不小心漏了
public interface Decodeable {
// 这个案例拿出来,还是强调细节,可能很多人觉得多写个public没什么,那怎么不把abstract也写上呢?
// 说到第还是习惯问题,不要写没有必要的废代码
// 这些细节idea是可以检查出来的,或者发布前全量扫描下代码也是可以修正的
public void decode() throws Exception;
}
// 重构后,接口中的行为声明不要带上public
public interface Decodeable {
void decode() throws Exception;
}
案例5
// Dubbo 源码,RpcResult
// 这个类中attachments是不可能为null的。这个从业务层面保证了的。所以这个方法中的判空是没有意义的。属于非代码
private Map<String, String> attachments = new HashMap<String, String>();
public void addAttachments(Map<String, String> map) {
if (map == null) {
return;
}
// attachments不可能为null,判空没有意义。如果真为空了,反而要看看这个类的结构是否哪边出问题了。
if (this.attachments == null) {
this.attachments = new HashMap<String, String>();
}
this.attachments.putAll(map);
}
// 重构后,删除了对attachments的判空操作
private Map<String, String> attachments = new HashMap<String, String>();
public void addAttachments(Map<String, String> map) {
if (map == null) {
return;
}
this.attachments.putAll(map);
}
有人说,Java
代码就像是老太太的裹脚布,又臭又长。我内心不想认同,当我接触了Python
,GO
语言后,对比发现有时候的确是这样。但我任然喜欢写Java。于此同时,我希望尽可能不要写费代码。合理利用封装,继承(不要排斥继承),多态,组合,完全能写出优雅的代码。
全部内容查看 优雅代码汇总篇