《Java开发手册——华山版》读书笔记

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
RDS MySQL Serverless 高可用系列,价值2615元额度,1个月
简介: 《Java开发手册——华山版》读书笔记

《Java开发手册——华山版》读书笔记


编程规约

命名风格

【06】:抽象类命名使用Abstract或Base开头;异常类命名使用Exception结尾;测试类命名以它要测试的类的名称开始,以Test结尾。

【08】:POJO类中布尔类型变量都不要加is前缀,否则部分框架解析会引起序列化错误。

说明:在本文MySQL规约中的建表约定第一条,表达是与否的值采用is_xxx的命名方式,所以,需要在<resultMap>设置从is_xxx到xxx的映射关系。

【14】:如果模块、接口、类、方法使用了设计模式,在命名时需体现出具体模式。


各层命名规约:

A) Service/DAO层方法命名规约

1) 获取单个对象的方法用get做前缀。

2) 获取多个对象的方法用list做前缀,复数形式结尾如:listObjects。

3) 获取统计值的方法用count做前缀。

4) 插入的方法用save/insert做前缀。

5) 删除的方法用remove/delete做前缀。

6) 修改的方法用update做前缀。


B) 领域模型命名规约

1) 数据对象:xxxDO,xxx即为数据表名。

2) 数据传输对象:xxxDTO,xxx为业务领域相关的名称。

3) 展示对象:xxxVO,xxx一般为网页名称。

4) POJO是DO/DTO/BO/VO的统称,禁止命名成xxxPOJO。


常量定义

【03】:不要使用一个常量类维护所有常量,要按常量功能进行归类,分开维护。

说明:大而全的常量类,杂乱无章,使用查找功能才能定位到修改的常量,不利于理解和维护。

正例:缓存相关常量放在类CacheConsts下;系统配置相关常量放在类ConfigConsts下。


【04】:常量的复用层次有五层:跨应用共享常量、应用内共享常量、子工程内共享常量、包内共享常量、类内共享常量。

1) 跨应用共享常量:放置在二方库中,通常是client.jar中的constant目录下。

2) 应用内共享常量:放置在一方库中,通常是子模块中的constant目录下。

3) 子工程内部共享常量:即在当前子工程的constant目录下。

4) 包内共享常量:即在当前包下单独的constant目录下。

5) 类内共享常量:直接在类内部private static final定义。


OOP规约

【07】:所有整型包装类对象之间值的比较,全部使用equals方法比较。

【08】:浮点数之间的等值判断,使用 BigDecimal 包装类进行判断;为了防止精度损失,禁止使用构造方法BigDecimal(double)的方式把double值转化为BigDecimal对象。优先推荐入参为String的构造方法,或使用BigDecimal的valueOf方法。

【21】:循环体内,字符串的连接方式,使用StringBuilder的append方法进行扩展。


集合处理

【01】:关于hashCode和equals的处理,

遵循如下规则:

1) 只要覆写equals,就必须覆写hashCode。

2) 因为Set存储的是不重复的对象,依据hashCode和equals进行判断,所以Set存储的对象必须覆写这两个方法。

3) 如果自定义对象作为Map的键,那么必须覆写hashCode和equals。

【02】:ArrayList的subList结果不可强转成ArrayList,否则会抛出 ClassCastException异常,即java.util.RandomAccessSubList cannot be cast to java.util.ArrayList。

【03】:使用Map的方法keySet()/values()/entrySet()返回集合对象时,不可以对其进行添加元素操作,否则会抛出UnsupportedOperationException异常。

【09】:泛型通配符<? extends T>来接收返回的数据,此写法的泛型集合不能使用add方法,而<? super T>不能使用get方法,作为接口调用赋值时易出错。 说明:扩展说一下PECS(Producer Extends Consumer Super)原则:

第一、频繁往外读取内容的,适合用<? extends T>。

第二、经常往里插入的,适合用<? super T>。

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

【15】:使用entrySet遍历Map类集合KV,而不是keySet方式进行遍历。

说明:keySet其实是遍历了2次,一次是转为Iterator对象,另一次是从hashMap中取出key所对应的value。而entrySet只是遍历了一次就把key和value都放到了entry中,效率更高。如果是JDK8,使用Map.forEach方法。

【16】:高度注意Map类集合K/V能不能存储null值的情况,如下表格:

image.png


【18】:利用Set元素唯一的特性,可以快速对一个集合进行去重操作,避免使用List的contains方法进行遍历、对比、去重操作。


并发处理(暂无)

控制语句

【01】:在一个switch块内,每个case要么通过continue/break/return等来终止,要么注释说明程序将继续执行到哪一个case为止;在一个switch块内,都必须包含一个default语句并且放在最后,即使它什么代码也没有。

【02】:当switch括号内的变量类型为String并且此变量为外部参数时,必须先进行null判断。

【03】:在高并发场景中,避免使用”等于”判断作为中断或退出的条件。 说明:如果并发控制没有处理好,容易产生等值判断被“击穿”的情况,使用大于或小于的区间判断条件来代替。

【05】:超过3层的 if-else 的逻辑判断代码可以使用卫语句、策略模式、状态模式等来实现,其中卫语句即代码逻辑先考虑失败、异常、中断、退出等直接返回的情况,以方法多个出口的方式,解决代码中判断分支嵌套的问题,这是逆向思维的体现。


其他

【05】:获取当前毫秒数System.currentTimeMillis(); 而不是new Date().getTime(); 说明:如果想获取更加精确的纳秒级时间值,使用System.nanoTime()的方式。在JDK8中,针对统计时间等场景,推荐使用Instant类。


异常日志

异常处理

日志规约

【01】:应用中不可直接使用日志系统(Log4j、Logback)中的API,而应依赖使用日志框架 SLF4J中的API,使用门面模式的日志框架,有利于维护和各个类的日志处理方式统一。

【04】:在日志输出时,字符串变量之间的拼接使用占位符的方式。 说明:因为String字符串的拼接会使用StringBuilder的append()方式,有一定的性能损耗。使用占位符仅是替换动作,可以有效提升性能。 正例:logger.debug(“Processing trade with id: {} and symbol: {}”, id, symbol);

【05】:对于trace/debug/info级别的日志输出,必须进行日志级别的开关判断。

说明:虽然在debug(参数)的方法体内第一行代码isDisabled(Level.DEBUG_INT)为真时(Slf4j的常见实现Log4j和Logback),就直接return,但是参数可能会进行字符串拼接运算。此外,如果debug(getName())这种参数内有getName()方法调用,无谓浪费方法调用的开销。

正例:

// 如果判断为真,那么可以输出trace和debug级别的日志
 if (logger.isDebugEnabled()) { 
  logger.debug("Current ID is: {} and name is: {}", id, getName());
  }


【08】:谨慎地记录日志。生产环境禁止输出debug日志;有选择地输出info日志;如果使用warn来记录刚上线时的业务行为信息,一定要注意日志输出量的问题,避免把服务器磁盘撑爆,并记得及时删除这些观察日志。

【09】:可以使用warn日志级别来记录用户输入参数错误的情况,避免用户投诉时,无所适从。如非必要,请不要在此场景打出error级别,避免频繁报警。 说明:注意日志输出的级别,error级别只记录系统逻辑出错、异常或者重要的错误信息。


单元测试

MySQL数据库

【01】:表达是与否概念的字段,必须使用is_xxx的方式命名,数据类型是unsigned tinyint(1表示是,0表示否)。

说明:任何字段如果为非负数,必须是unsigned。 注意:POJO类中的任何布尔类型的变量,都不要加is前缀,所以,需要在设置从is_xxx到Xxx的映射关系。数据库表示是与否的值,使用tinyint类型,坚持is_xxx的命名方式是为了明确其取值含义与取值范围。 正例:表达逻辑删除的字段名is_deleted,1表示删除,0表示未删除。

【02】:表名、字段名必须使用小写字母或数字,禁止出现数字开头,禁止两个下划线中间只出现数字。数据库字段名的修改代价很大,因为无法进行预发布,所以字段名称需要慎重考虑。

【04】:禁用保留字,如desc、range、match、delayed等,请参考MySQL官方保留字。

【05】:主键索引名为pk_字段名;唯一索引名为uk_字段名;普通索引名则为idx_字段名。

说明:pk_ 即primary key;uk_ 即 unique key;idx_ 即index的简称。

【09】:表必备三字段:id, create_time, update_time。

说明:

其中id必为主键,类型为bigint unsigned、单表时自增、步长为1。

create_time, update_time的类型均为datetime类型。

【14】:单表行数超过500万行或者单表容量超过2GB,才推荐进行分库分表。

说明:如果预计三年后的数据量根本达不到这个级别,请不要在创建表时就分库分表。


索引规约

【07】:利用延迟关联或者子查询优化超多分页场景。

说明:MySQL并不是跳过offset行,而是取offset+N行,然后返回放弃前offset行,返回N行,那当offset特别大的时候,效率就非常的低下,要么控制返回的总页数,要么对超过特定阈值的页数进行SQL改写。

正例:先快速定位需要获取的id段,然后再关联: SELECT a.* FROM 表1 a, (select id from 表1 where 条件 LIMIT 100000,20 ) b where a.id=b.id

【08】:SQL性能优化的目标:至少要达到 range 级别,要求是ref级别,如果可以是consts最好。 说明:

1) consts 单表中最多只有一个匹配行(主键或者唯一索引),在优化阶段即可读取到数据。

2) ref 指的是使用普通的索引(normal index)。

3) range 对索引进行范围检索。

反例:explain表的结果,type=index,索引物理文件全扫描,速度非常慢,这个index级别比较range还低,与全表扫描是小巫见大巫。


SQL语句

【01】:不要使用count(列名)或count(常量)来替代count(*),count(*)是SQL92定义的标准统计行数的语法,跟数据库无关,跟NULL和非NULL无关。 说明:count(*)会统计值为NULL的行,而count(列名)不会统计此列为NULL值的行。

【02】:count(distinct col) 计算该列除NULL之外的不重复行数,注意 count(distinct col1, col2) 如果其中一列全为NULL,那么即使另一列有不同的值,也返回为0。

【03】:当某一列的值全是NULL时,count(col)的返回结果为0,但sum(col)的返回结果为NULL,因此使用sum()时需注意NPE问题。

正例:使用如下方式来避免sum的NPE问题:SELECT IFNULL(SUM(column), 0) FROM table;

【08】:数据订正(特别是删除、修改记录操作)时,要先select,避免出现误删除,确认无误才能执行更新语句。

【09】:in操作能避免则避免,若实在避免不了,需要仔细评估in后边的集合元素数量,控制在1000个之内。


相关实践学习
基于CentOS快速搭建LAMP环境
本教程介绍如何搭建LAMP环境,其中LAMP分别代表Linux、Apache、MySQL和PHP。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
目录
相关文章
|
6天前
|
存储 Java 数据库连接
使用Java开发桌面应用程序
使用Java开发桌面应用程序
15 0
|
6天前
|
Java API 开发工具
java与Android开发入门指南
java与Android开发入门指南
14 0
|
6天前
|
分布式计算 负载均衡 Java
构建高可用性Java应用:介绍分布式系统设计与开发
构建高可用性Java应用:介绍分布式系统设计与开发
11 0
|
6天前
|
前端开发 安全 Java
使用Spring框架加速Java开发
使用Spring框架加速Java开发
52 0
|
6天前
|
前端开发 JavaScript Java
Java与Web开发的结合:JSP与Servlet
Java与Web开发的结合:JSP与Servlet
10 0
|
6天前
|
设计模式 算法 Java
设计模式在Java开发中的应用
设计模式在Java开发中的应用
18 0
|
6天前
|
监控 Java Maven
揭秘Java Agent技术:解锁Java工具开发的新境界
作为JDK提供的关键机制,Java Agent技术不仅为Java工具的开发者提供了一个强大的框架,还为性能监控、故障诊断和动态代码修改等领域带来了革命性的变革。本文旨在全面解析Java Agent技术的应用场景以及实现方式,特别是静态加载模式和动态加载模式这两种关键模式。
34 0
|
7天前
|
存储 Java 开发者
探索Java开发中触发空指针异常的场景
作为一名后端开发者在Java编程的世界中,想必大家对空指针并不陌生,空指针异常是一种常见而又令人头疼的问题,它可能会在我们最不经意的时候突然出现,给我们的代码带来困扰,甚至导致系统的不稳定性,而且最可怕的是有时候不能及时定位到它的具体位置。针对这个问题,我们需要深入了解触发空指针异常的代码场景,并寻找有效的方法来识别和处理这些异常情况,而且我觉得空指针异常是每个Java开发者都可能面临的挑战,但只要我们深入了解它的触发场景,并采取适当的预防和处理措施,我们就能够更好地应对这个问题。那么本文就来分享一下实际开发中一些常见的触发空指针异常的代码场景,并分享如何有效地识别和处理这些异常情况。
21 1
探索Java开发中触发空指针异常的场景
|
7天前
|
传感器 人工智能 前端开发
JAVA语言VUE2+Spring boot+MySQL开发的智慧校园系统源码(电子班牌可人脸识别)Saas 模式
智慧校园电子班牌,坐落于班级的门口,适合于各类型学校的场景应用,班级学校日常内容更新可由班级自行管理,也可由学校统一管理。让我们一起看看,电子班牌有哪些功能呢?
98 4
JAVA语言VUE2+Spring boot+MySQL开发的智慧校园系统源码(电子班牌可人脸识别)Saas 模式
|
15天前
|
Java 索引
Java String应用与开发
Java String应用与开发
22 0