Java规范思维导图
2023-03-04 10:29:47 0 举报
AI智能生成
简单总结下 Java 开发规范
作者其他创作
大纲/内容
全小写/单数
包名
UpperCamelCase
类名
lower camel case
方法名、参数名、成员变量、局部变量
全部大写,单词间用下划线隔开
常量
命名体现具体模式
设计模式
Service /ServiceImpl
接口/实现类
持久层对象
PO
前端视图对象
VO
数据访问层接口
DAO
业务层对象
BO
数据传输对象
DTO
领域模型POJO
交互对象
dto
对象转化
assembler
通讯接口
facade
接口与通讯层
User Interface
组装/接口/实现
service/impl
应用层
Application
实体
entity
值对象
pojo
领域事件
domain event
仓储
repository
领域模型/业务层
domain
客户端/这个moudle 提供出去的接口
client
服务端/这个moudle 调用其它moudle 的封装
server
基础设施层
infrastructure
驱动领域模型
命名
二方库:公司内部发布到中央仓库,可供公司内部其它应用依赖的库(jar 包)
二方库的constant
跨应用共享常量
一方库:本工程内部子项目模块依赖的库(jar 包)
一方库的constant
应用内共享常量
当前子工程的constant
子工程内共享常量
当前包单独的constant
包内共享常量
类内部 private static final 定义
类内共享常量
单行字节数不超过120,超出换行
单方法总行数不超过 80
代码格式
复写方法 @Override
不能使用过时方法
过时方法 @Deprecated
Object 的 equals 方法容易抛空指针异常,应使用常量或确定有值的对象来调用equals。
对于 Integer var = ? 在-128 至 127 范围内的赋值,Integer 对象是在 IntegerCache.cache 产生,会复用已有对象,这个区间内的 Integer 值可以直接使用==进行判断,但是这个区间之外的所有数据,都会在堆上产生,并不会复用已有对象,这是一个大坑,推荐使用 equals 方法进行判断
所有整型包装类对象之间值的比较,全部使用 equals 方法比较
浮点数转成 BigDecimal 进行值判断
先转为字符串,然后转成 BigDeciaml对象
禁止使用 BigDecimal(double)的方式把 double 值转化为 BigDecimal 对象
浮点数之间的等值判断,基本数据类型不能用==来比较,包装数据类型不能用equals 来判断。
equals
数据库的查询结果可能是 null,因为自动拆箱,用基本数据类型接收有 NPE 风险
所有的 POJO 类属性必须使用包装数据类型
RPC 方法的返回值和参数必须使用包装数据类型
局部变量使用基本数据类型
构造方法里面禁止加入任何业务逻辑,如果有初始化逻辑,请放在 init 方法中
循环体内,字符串的连接方式,使用 StringBuilder 的 append 方法进行扩展
OOP 面向对象编程
只要覆写 equals,就必须覆写 hashCode
不要在 foreach 循环里进行元素的 remove/add 操作。remove 元素请使用Iterator 方式,如果并发操作,需要对 Iterator 对象加锁。
使用 Map 的方法 keySet()/values()/entrySet()返回集合对象时,不可以对其进行添加元素操作,否则会抛出 UnsupportedOperationException 异常
ArrayList 的 subList 结果不可强转成 ArrayList,否则会抛出 ClassCastException 异常,即 java.util.RandomAccessSubList cannot be cast to java.util.ArrayList。
Collections 类返回的对象,如:emptyList()/singletonList()等都是 immutable list,不可对其进行添加或者删除元素的操作。
使用工具类 Arrays.asList()把数组转换成集合时,不能使用其修改集合相关的方法,它的 add/remove/clear 方法会抛出 UnsupportedOperationException 异常
x,y 的比较结果和 y,x 的比较结果相反
x>y,y>z,则 x>z
x=y,则 x,z 比较结果和 y,z 比较结果相同
在 JDK7 版本及以上,Comparator 实现类要满足如下三个条件,不然 Arrays.sort,Collections.sort 会抛 IllegalArgumentException 异常
无法确定集合大小或频繁增删集合数据的时候,使用列表集合,LinekedList;获取集合对象后用于查询,使用数组集合 ArrayList;
集合
获取单例对象需要保证线程安全,其中的方法也要保证线程安全。
创建线程或线程池时请指定有意义的线程名称,方便出错时回溯。
线程资源必须通过线程池提供,不允许在应用中自行显式创建线程。
线程池不允许使用 Executors 去创建,而是通过 ThreadPoolExecutor 的方式,这样的处理方式让写的同学更加明确线程池的运行规则,规避资源耗尽的风险。
SimpleDateFormat 是线程不安全的类,一般不要定义为 static 变量,如果定义为static,必须加锁,或者使用 DateUtils 工具类
必须回收自定义的 ThreadLocal 变量,尤其在线程池场景下,线程经常会被复用,如果不清理自定义的 ThreadLocal 变量,可能会影响后续业务逻辑和造成内存泄露等问题。尽量在代理中使用 try-finally 块进行回收
合理减少锁区域
高并发时,同步调用应该去考量锁的性能损耗。能用无锁数据结构,就不要用锁;能锁区块,就不要锁整个方法体;能用对象锁,就不要用类锁。
对多个资源、数据库表、对象同时加锁时,需要保持一致的加锁顺序,否则可能会造成死锁。
在使用阻塞等待获取锁的方式中,必须在 try 代码块之外,并且在加锁方法与 try 代码块之间没有任何可能抛出异常的方法调用,避免加锁成功后,在 finally 中无法解锁。
在使用尝试机制来获取锁的方式中,进入业务代码块之前,必须先判断当前线程是否持有锁。锁的释放规则与锁的阻塞等待方式相同。
并发修改同一记录时,避免更新丢失,需要加锁。要么在应用层加锁,要么在缓存加锁,要么在数据库层使用乐观锁,使用 version 作为更新依据。
多线程并行处理定时任务时,Timer 运行多个 TimeTask 时,只要其中之一没有捕获抛出的异常,其它任务便会自动终止运行,如果在处理定时任务时使用ScheduledExecutorService 则没有这个问题
HashMap 在容量不够进行 resize 时由于高并发可能出现死链,导致 CPU 飙升,在开发过程中可以使用其它数据结构或加锁来规避此风险
并发
超过 3 层的 if-else 的逻辑判断代码可以使用卫语句、策略模式、状态模式等来实现,其中卫语句即代码逻辑先考虑失败、异常、中断、退出等直接返回的情况,以方法多个出口的方式,解决代码中判断分支嵌套的问题,这是逆向思维的体现
子主题
if 语句
循环体中的语句要考量性能,以下操作尽量移至循环体外处理,如定义对象、变量、获取数据库连接,进行不必要的 try-catch 操作(这个 try-catch 是否可以移至循环体外)
尽量避免采用取反逻辑运算符
控制语句
类、类属性、类方法的注释必须使用 Javadoc 规范,使用/**内容*/格式,不得使用 // xxx 方式
所有的抽象方法(包括接口中的方法)必须要用 Javadoc 注释、除了返回值、参数、异常说明外,还必须指出该方法做什么事情,实现什么功能
所有的枚举类型字段必须要有注释,说明每个数据项的用途
代码修改的同时,注释也要进行相应的修改,尤其是参数、返回值、异常、核心逻辑等的修改。
注释
存储方案和底层数据结构的设计获得评审一致通过,并沉淀成为文档
在需求分析阶段,如果与系统交互的 User 超过一类并且相关的 User Case 超过 5个,使用用例图来表达更加清晰的结构化需求
如果某个业务对象的状态超过 3 个,使用状态图来表达并且明确状态变化的各个触发条件
如果系统中某个功能的调用链路上的涉及对象超过 3 个,使用时序图来表达并且明确各调用环节的输入与输出
如果系统中模型类超过 5 个,并且存在复杂的依赖关系,使用类图来表达并且明确类之间的关系
如果系统中超过 2 个对象之间存在协作关系,并且需要表示复杂的处理流程,使用活动图来表示
类在设计与实现时要符合单一原则
系统设计时,注意对扩展开放,对修改闭合
系统设计阶段,共性业务或公共行为抽取出来公共模块、公共配置、公共类、公共方法等,避免出现重复代码或重复配置的情况
系统设计主要目的是明确需求、理顺逻辑、后期维护,次要目的用于指导编码
确定系统边界。确定系统在技术层面上的做与不做
确定系统内模块之间的关系。确定模块之间的依赖关系及模块的宏观输入与输出
确定指导后续设计与演化的原则。使后续的子系统或模块设计在规定的框架内继续演化
确定非功能性需求。非功能性需求是指安全性、可用性、可扩展性等
系统架构设计的目的
设计
Java 规范思维导图
0 条评论
回复 删除
下一页