快速导航
Java代码规范
- 类名 UpperCamelCase
- 方法名、参数名、成员变量、局部变量 lowerCamelCase
- 常量名大写+下划线 MAX_STOCK_COUNT
- 包名一律小写 experiment
- 大括号内为空,则简洁地写成{}
- 左大括号前不换行;左大括号后换行;右大括号前换行; 右大括号后还有 else 等代码则不换行;表示终止的右大括号后必须换行。
- 左小括号和右边相邻字符之间不出现空格
- 右小括号和左边相邻字符之间不出现空格
- 而左大括号前需要加空格
- if/for/while/switch/do 等保留字与括号之间都必须加空格。
- 任何二目、三目运算符的左右两边都需要加一个空格。
- 任何二目、三目运算符的左右两边都需要加一个空格。
- 注释的双斜线与注释内容之间有且仅有一个空格。
- 右括号与强制转换值之间不需要任何空格隔开。
- 右括号与强制转换值之间不需要任何空格隔开。
- 避免通过一个类的对象引用访问此类的静态变量或静态方法,无谓增加编译器解析成本,直接用类名来访问即可。
- 所有的覆写方法,必须加@Override 注解。
- Object 的 equals 方法容易抛空指针异常,应使用常量或确定有值的对象来调用 equals。
- 所有整型包装类对象之间值的比较,全部使用 equals 方法比较。
- 任何货币金额,均以最小货币单位且整型类型来进行存储。
- 浮点数之间的等值判断,基本数据类型不能用==来比较,包装数据类型不能用 equals来判断。
- BigDecimal 的等值比较应使用 compareTo()方法,而不是 equals()方法。equals()方法会比较值和精度(1.0 与 1.00 返回结果为 false),而 compareTo()则会忽略精度。
- 定义数据对象 DO 类时,属性类型要与数据库字段类型相匹配。
- 禁止使用构造方法 BigDecimal(double)的方式把 double 值转化为 BigDecimal 对象。
- 日期格式化时,传入 pattern 中表示年份统一使用小写的 y。
- 在日期格式中分清楚大写的 M 和小写的 m,大写的 H 和小写的 h 分别指代的意义。表示月份是大写的 M;表示分钟则是小写的 m;24 小时制的是大写的 H; 12 小时制的则是小写的 h。
- 获取当前毫秒数:System.currentTimeMillis()
- 不允许在程序任何地方中使用:1)java.sql.Date。 2)java.sql.Time。 3)java.sql.Timestamp。
- 不要在程序中写死一年为 365 天
- 使用枚举值来指代月份。
- 创建线程或线程池时请指定有意义的线程名称,方便出错时回溯。
- 线程资源必须通过线程池提供,不允许在应用中自行显式创建线程。
- 线程池不允许使用 Executors 去创建,而是通过 ThreadPoolExecutor 的方式,这样的处理方式让写的同学更加明确线程池的运行规则,规避资源耗尽的风险。
- SimpleDateFormat 是线程不安全的类,一般不要定义为 static 变量,如果定义为 static,必须加锁,或者使用 DateUtils 工具类。
- 必须回收自定义的 ThreadLocal 变量,尤其在线程池场景下,线程经常会被复用,如果不清理自定义的 ThreadLocal 变量,可能会影响后续业务逻辑和造成内存泄露等问题。尽量在代理中使用 try-finally 块进行回收。
- 高并发时,同步调用应该去考量锁的性能损耗。能用无锁数据结构,就不要用锁;能锁区块,就不要锁整个方法体;能用对象锁,就不要用类锁。
- 对多个资源、数据库表、对象同时加锁时,需要保持一致的加锁顺序,否则可能会造成死锁。
- 在使用阻塞等待获取锁的方式中,必须在 try 代码块之外,并且在加锁方法与 try 代码块之间没有任何可能抛出异常的方法调用,避免加锁成功后,在 finally 中无法解锁。
- 在使用尝试机制来获取锁的方式中,进入业务代码块之前,必须先判断当前线程是否持有锁。锁的释放规则与锁的阻塞等待方式相同。
- 并发修改同一记录时,避免更新丢失,需要加锁。要么在应用层加锁,要么在缓存加锁,要么在数据库层使用乐观锁,使用 version 作为更新依据。
- 多线程并行处理定时任务时,Timer 运行多个 Timetask 时,只要其中之一没有捕获抛出的异常,其它任务便会自动终止运行,使用 ScheduledExecutorService 则没有这个问题。
- 在一个 switch 块内,每个 case 要么通过 continue/break/return 等来终止,要么注释说明程序将继续执行到哪一个 case 为止;在一个 switch 块内,都必须包含一个 default语句并且放在最后,即使它什么代码也没有。、
- 当 switch 括号内的变量类型为 String 并且此变量为外部参数时,必须先进行 null判断。
- 在 if/else/for/while/do 语句中必须使用大括号。
- 三目运算符 condition? 表达式 1 : 表达式 2 中,高度注意表达式 1 和 2 在类型对齐时,可能抛出因自动拆箱导致的 NPE 异常。
- 在高并发场景中,避免使用”等于”判断作为中断或退出的条件。
- 类、类属性、类方法的注释必须使用 Javadoc 规范,使用注释,注意与代码对齐。
- 所有的枚举类型字段必须要有注释,说明每个数据项的用途。
- 前后端交互的 API,需要明确协议、域名、路径、请求方法、请求内容、状态码、响应体。
- 协议:生产环境必须使用 HTTPS。
- 1) 协议:生产环境必须使用 HTTPS。
- 2) 路径:每一个 API 需对应一个路径,表示 API 具体的请求地址:
- a) 代表一种资源,只能为名词,推荐使用复数,不能为动词,请求方法已经表达动作意义。
- b) URL 路径不能使用大写,单词如果需要分隔,统一使用下划线。
- c) 路径禁止携带表示请求内容类型的后缀,比如".json",".xml",通过 accept 头表达即可。
- 3) 请求方法:对具体操作的定义,常见的请求方法如下:
- a) GET:从服务器取出资源。
- b) POST:在服务器新建一个资源。
- c) PUT:在服务器更新资源。
- d) DELETE:从服务器删除资源。
- 4) 请求内容:URL 带的参数必须无敏感信息或符合安全要求;body 里带参数时必须设置 Content-Type。
- 5) 响应体:响应体 body 可放置多种数据类型,由 Content-Type 头来确定。
- 前后端数据列表相关的接口返回,如果为空,则返回空数组[]或空集合{}。
- 服务端发生错误时,返回给前端的响应信息必须包含 HTTP 状态码,errorCode、errorMessage、用户提示信息四个部分。
- Java 类库中定义的可以通过预检查方式规避的 RuntimeException 异常不应该通过catch 的方式来处理,比如:NullPointerException,IndexOutOfBoundsException 等等。
- 异常捕获后不要用来做流程控制,条件控制。
- catch 时请分清稳定代码和非稳定代码,稳定代码指的是无论如何不会出错的代码。对于非稳定代码的 catch 尽可能进行区分异常类型,再做对应的异常处理。
- 捕获异常是为了处理它,不要捕获了却什么都不处理而抛弃之,如果不想处理它,请将该异常抛给它的调用者。最外层的业务使用者,必须处理异常,将其转化为用户可以理解的内容。
- 事务场景中,抛出异常被 catch 后,如果需要回滚,一定要注意手动回滚事务。
- finally 块必须对资源对象、流对象进行关闭,有异常也要做 try-catch。
- 不要在 finally 块中使用 return。try 块中的 return 语句执行成功后,并不马上返回,而是继续执行 finally 块中的语句,如果此处存在 return 语句,则在此直接返回,无情丢弃掉 try 块中的返回点。
- 捕获异常与抛异常,必须是完全匹配,或者捕获异常是抛异常的父类。
- 存储方案和底层数据结构的设计获得评审一致通过,并沉淀成为文档。
- 在需求分析阶段,如果与系统交互的 User 超过一类并且相关的 User Case 超过 5 个,使用用例图来表达更加清晰的结构化需求。
- 如果某个业务对象的状态超过 3 个,使用状态图来表达并且明确状态变化的各个触发条件。
- 如果系统中某个功能的调用链路上的涉及对象超过 3 个,使用时序图来表达并且明确各调用环节的输入与输出。
- 如果系统中模型类超过 5 个,并且存在复杂的依赖关系,使用类图来表达并且明确类之间的关系。
- 如果系统中超过 2 个对象之间存在协作关系,并且需要表示复杂的处理流程,使用活动图来表示。