【周一电台】阿里巴巴的Java开发手册(黄山版)来了

0. 阅读完本文你将会学会

写出更优雅高效的Java代码

1. 前言

周六逛B乎的时候正好刷到这样一个问题"Java开发手册(黄山版)怎么样?",我仔细一看这不是孤尽老师的著作吗?居然已经更新到了黄山版。

上次看这本小册子的时候还是上次——19年的时候我看的华山版的。再往前那就是17年的第一版了,当时是在阿里的公众号下载的,后来还买了实体的《Java开发手册》和《码出高效》两本书。

其实这本小册子并不是什么深度的内容,但是却让我受益匪浅——你写不出复杂高深的代码,但是至少能写出规范、干净、同事看了不喊“卧槽”而是喊“卧槽牛逼”的代码。

在这篇文章中我将会挑选几条手册中的编程规约做一个简单的导读。

友情提示,文末有手册下载方式哦。

对软件来说,适当的 规范和标准绝不是消灭代码内容的创造性、优雅性,而是限制过度个性化,以一种普遍认可的统一方式一起做事,提升协作效率,降低沟通成本。代码的字里行间流淌的是软件系统的血液,代码质 量的提升是尽可能少踩坑,杜绝踩重复的坑,切实提升系统稳定性,码出质量。

2. 编程规约导读

2.1 禁用魔法值

不允许任何魔法值(即未经预先定义的常量)直接出现在代码中。

// 反例: 开发者 A 定义了缓存的 key。

String key ="Id#taobao_"+ tradeId;

cache.put(key, value);

// 开发者 B 使用缓存时直接复制少了下划线,

// 即 key 是"Id#taobao"+ tradeId,导致出现故障。

String key ="Id#taobao"+ tradeId;

cache.get(key);

魔法值指的是代码中没有任何定义,直接像魔法一样凭空出现的值,可以是数字、字符串等。

这是我印象中比较深的一条强制性规约。

当我刚入这行的开始写代码的时候,魔法值满天飞,怎么方便怎么来。根本不会考虑这样的问题,但是后来这样做的恶性后果也就出现了。

重复性的魔法值,不够简洁,逼死喜欢复用的强迫症!

容易出现像上面反例一样的错误,比如下划线少了啊或者一个单词拼错了。

魔法值难以简明地阐述其含义。比如,代码中直接出现的"0"和"1",谁知道它的含义呢?

所以,我们是可以通过静态常量或者枚举来定义你的常量,这样就可以把魔法值消灭殆尽。

2.2 访问权限控制从严

类成员与方法访问控制从严。

如果不允许外部直接通过 new 来创建对象,那么构造方法必须是 private。

工具类不允许有 public 或 default 构造方法。

类非 static 成员变量并且与子类共享,必须是 protected。

类非 static 成员变量并且仅在本类使用,必须是 private。

类 static 成员变量如果仅在本类使用,必须是 private。

若是 static 成员变量,考虑是否为 final。

类成员方法只供类内部调用,必须是 private。

类成员方法只对继承类公开,那么限制为 protected。

这条是推荐性编程规约,其实这样的规约正是体现了Java的特性之一——封装性。

对于任何类、方法、参数、变量,我们都应该严格控制其访问范围。太过宽泛的访问范围,不利于模块解耦。

我自己写代码的时候,也是private够用就用private。

孤尽在手册里提出了一个很有意思的问题:

如果是一个 private 的方法,想删除就删除,可是一个 public 的 service 成员方法或成员变量,删除一下,不得手心冒点汗吗?

他做了这样一个比喻:

变量像自己的小孩,尽量在自己的视线内,变量作用域太大,无限制的到处跑,那么你会担心的。

我觉得这真是说到点子上了。

2.3 for循环中list禁用remove/add

不要在 foreach 循环里进行元素的 remove / add 操作。remove 元素请使用 iterator 方式, 如果并发操作,需要对 iterator 对象加锁。

//正例:

List list = new ArrayList<>();

list.add("1");

list.add("2");

Iterator iterator = list.iterator();

while(iterator.hasNext()) {

String item = iterator.next();

if(删除元素的条件) {

iterator.remove();

}

}

//反例:

for(String item : list) {

if("1".equals(item)) {

list.remove(item);

}

}

这条强制性规约的坑我也踩过,在反例中,当它执行了remove操作,会报如下错。

java.util.ConcurrentModificationException

具体的原因不在此文赘述,有兴趣的读者朋友可以网上查阅。

2.4 命名复杂布尔表达式

除常用方法(如 getXxx / isXxx)等外不要在条件判断中执行其它复杂的语句,将复杂逻辑判 断的结果赋值给一个有意义的布尔变量名,以提高可读性。

这条推荐性规约也是我推崇备至的。因为业务需要,我们可能在if语句中写出非常复杂的逻辑表达式。与、或、取反混合运算,甚至各种方法调用,理解起来非常难。

如果我们赋予这样一个逻辑表达式一个很好理解的名字(我觉得比注释更简洁易懂方便),则是一件令人赏心悦目的事情。

我们来看一个对比的例子:

正例:

// 伪代码如下

final boolean existed = (file.open(fileName,"w") != null) && (...) || (...);

if(existed) { ... }

反例:

public final void acquire(long arg) {

if(!tryAcquire(arg) && acquireQueued(addWaiter(Node.EXCLUSIVE), arg)){

selfInterrupt();

}

}

2.5 异常处理

catch 时请分清稳定代码和非稳定代码,稳定代码指的是无论如何不会出错的代码。对于非稳定 代码的 catch 尽可能进行区分异常类型,再做对应的异常处理。

看到这条强制性规约的时候,我老脸一红。

因为我曾经也犯过这样的错——对大段代码进行try-catch,这样做会使程序无法根据不同的异常做出正确的应激反应,也不利于定位问题,这是一种不负责任的表现。

用户注册的场景中,如果用户输入非法字符,或用户名称已存在,或用户输入密码过于简单,我们应该在程序上作出分门别类的判断,并提示给用户。

2.6 日志规约

生产环境禁止使用 System.out 或 System.err 输出或使用 e.printStackTrace() 打印异常堆栈。

使用e.printStackTrace() 打印日志容易占用太多内存,造成锁死。

要打印字符串输出到控制台上,需要字符串常量池所在的内存块有足够的空间。然而,因为e.printStackTrace() 语句要产生的字符串记录的是堆栈信息,太长太多,内存被填满了!大量线程产出字符串产出到一半,等待有内存被释放,锁死了,导致整个应用挂掉了。

另外,日志交错混合,不易读。

printStackTrace()默认使用了System.err输出流进行输出,与System.out是两个不同的输出流,那么在打印时自然就形成了交叉。再就是输出流是有缓冲区的,所以对于什么时候具体输出也形成了随机。

一般打印错误日志的时候我们都是用日志框架的log.error("",e),基本够用了。

2.7 数据库

小数类型为 decimal,禁止使用 float 和 double。

这是一条强制性规约,在存储的时候,float 和 double 都存在精度损失的问题,很可能在比较值的时候,得到不正确的结果。

如果存储的数据范围超过 decimal 的范围,建议将数据拆成整数和小数并分开存储。

3.结语

以上是我从手册中摘录的几条规约,加之一些简单的导读。不知道各位看官老爷们有没有一些似曾相识的感觉呢?

手册一共有七个章节,基本上囊括了Java程序员写代码的方方面面。

如何获取手册,写出更优雅高效的代码,请关注我的公众号"花园野人",回复"pdf1",即可获取孤尽老师的Java开发手册。

往期精选

Java8-15的新特性,你知道几个?

从开源创业之星到造炸弹,最后删库跑路,他经历了什么?

11个值得掌握的Java代码性能优化技巧

感谢收看本期的翊君@周一电台。如果你觉得还不错的话,快给我三连支持一下吧,咱们下期不见不散呐。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
禁止转载,如需转载请通过简信或评论联系作者。
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,036评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,046评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,411评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,622评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,661评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,521评论 1 304
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,288评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,200评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,644评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,837评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,953评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,673评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,281评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,889评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,011评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,119评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,901评论 2 355

推荐阅读更多精彩内容