写点什么

解读《Java 开发手册 (泰山版)》- 会当凌绝顶,一览众山小

用户头像
xcbeyond
关注
发布于: 2021 年 01 月 09 日
解读《Java开发手册(泰山版)》- 会当凌绝顶,一览众山小

阿里的《Java 开发手册》被 Java 开发者所拜读,基本人手一册,就在去年(2020.04.22)发布了泰山版 - 会当凌绝顶,一览众山小,而这次发布新增了很多干货内容,在此,给大家分享一下,是时候更新你的手册了。


从文末【附 1:版本历史】,记录来看,本次泰山版更新内容如下:


  • 发布错误码统一解决方案

  • 新增 34 条新规约。比如,日期时间的闰年、闰月问题,三目运算的自动拆箱,SQL 查询的表别名限定,Collectors 类的 toMap()方法使用注意等。

  • 修改描述 90 处。比如,阻塞等待锁、建表的小数类型等。

  • 完善若干处示例。比如,ISNULL 的示例等。


在此,尝鲜解读,分享给大家。


(规范性的东西,在实际使用过程中,只是作为一种通用的参考,切勿过分照搬!)


一、错误码


之前版本中没有涉及过关于“错误码”的内容,而在这个版本中新增了一小节来描述了“错误码”部分,并做了详细的说明。


错误码,作为任何一个系统中必不可少的要素,但好多时候错误码的不规范、不统一使用,便会对后期开发、使用造成很大的困扰。本次版本,“错误码”的出现,给广大开发者在定义错误码时提供的参考、建议,可谓福利。


具体规范如下:


  1. 【强制】错误码的制定原则:快速溯源、简单易记、沟通标准化

  2. 【强制】错误码不体现版本号和错误等级信息。

  3. 【强制】全部正常,但不得不填充错误码时返回五个零:00000。

  4. 【强制】错误码为字符串类型。

  5. 【强制】编号不与公司业务架构,更不与组织架构挂钩,一切与平台先到先申请的原则进行,审批生效,编号即被永久固定。

  6. 【强制】错误码使用者避免随意定义新的错误码。

  7. 【强制】错误码不能直接输出给用户作为提示信息使用。

  8. 【参考】错误码分为一级宏观错误码、二级宏观错误码、三级宏观错误码。即:分类定义错误码,便于归类。

  9. ……


个人建议:


  • 错误码格式一定统一、规范化,切勿杂乱无章定义。

  • 分类定义错误码,便于归类。即:按实际来进行多级分类,如前两位代指服务编号,次一位代指错误类别,再次之代指具体错误编号。

  • 错误码切记重复。


二、日期时间规范


新增"日期时间"的编程规范,都是些细节问题,稍加思考、留意,就可避免。规范如下:


  1. 【强制】日期格式化时,传入 pattern 中表示年份统一使用小写的 y。

  2. 【强制】在日期格式中分清楚大写的 M 和小写的 m,大写的 H 和小写的 h 分别指代的意义。

  3. 【强制】获取当前毫秒数:System.currentTimeMillis(); 而不是 new Date().getTime()。

  4. 【强制】不允许在程序任何地方中使用:1)java.sql.Date 2)java.sql.Time 3)java.sql.Timestamp。

  5. 【强制】不要在程序中写死一年为 365 天,避免在公历闰年时出现日期转换错误或程序逻辑错误。


稍有些常识的人都知道,不可能每年都是 365 天的。


正例:

// 获取今年的天数int daysOfThisYear = LocalDate.now().lengthOfYear();
// 获取指定某年的天数LocalDate.of(2011, 1, 1).lengthOfYear();
复制代码


反例:

// 第一种情况:在闰年 366 天时,出现数组越界异常int[] dayArray = new int[365];
// 第二种情况:一年有效期的会员制,今年 1 月 26 日注册,硬编码 365 返回的却是 1 月 25 日Calendar calendar = Calendar.getInstance();calendar.set(2020, 1, 26);calendar.add(Calendar.DATE, 365);
复制代码


  1. 【推荐】避免公历闰年 2 月问题。闰年的 2 月份有 29 天,一年后的那一天不可能是 2 月 29 日。

  2. 【推荐】使用枚举值来指代月份。如果使用数字,注意 Date,Calendar 等日期相关类的月份 month 取值在 0-11 之间。


三、三目运算符


【强制】三目运算符 condition? 表达式 1 : 表达式 2 中,高度注意表达式 1 和 2 在类型对齐时,可能抛出因自动拆箱导致的 NPE(NullPointerException) 异常。


以下两种场景会触发类型对齐的拆箱操作:

1) 表达式 1 或表达式 2 的值只要有一个是原始类型。


2) 表达式 1 或表达式 2 的值的类型不一致,会强制拆箱升级成表示范围更大的那个类型。


反例:

Integer a = 1;Integer b = 2;Integer c = null;Boolean flag = false;
// a*b 的结果是 int 类型,那么 c 会强制拆箱成 int 类型,抛出 NPE 异常Integer result=(flag? a*b : c);
复制代码


四、表别名


【强制】对于数据库中表记录的查询和变更,只要涉及多个表,都需要在列名前加表的别名(或表名)进行限定。


说明:对多表进行查询记录、更新记录、删除记录时,如果对操作列没有限定表的别名(或表名),并且操作列在多个表中存在时,就会抛异常。


正例:select t1.name from table_first as t1 , table_second as t2 where t1.id=t2.id;


反例:在某业务中,由于多表关联查询语句没有加表的别名(或表名)的限制,正常运行两年后,最近在某个表中增加一个同名字段,在预发布环境做数据库变更后,线上查询语句出现出 1052 异常:Column 'name' in field list is ambiguous。


【推荐】SQL 语句中表的别名前加 as,并且以 t1、t2、t3、...的顺序依次命名。说明:


1)别名可以是表的简称,或者是根据表出现的顺序,以 t1、t2、t3 的方式命名。


2)别名前加 as 使别名更容易识别。


正例:select t1.name from table_first as t1, table_second as t2 where t1.id=t2.id;


五、总结


《Java 开发手册》,在许多公司常常作为新员工的必读资料,作为公司开发规范的参考,在广大 Java 开发者的职业生涯中发挥着重要的作用。


以上只是针对其中很少部分内容的解读、复述,在我们日常开发中很有借鉴、参考意义,至少它会避免我们犯很多错误。

发布于: 2021 年 01 月 09 日阅读数: 31
用户头像

xcbeyond

关注

不为别的,只为技术沉淀、分享。 2019.06.20 加入

公众号:程序猿技术大咖,专注于技术输出、分享。

评论

发布
暂无评论
解读《Java开发手册(泰山版)》- 会当凌绝顶,一览众山小