Java 开发规范(更新中)

本文详细介绍了Java编程中的命名规范,包括包名、类名、常量、变量的命名规则,以及代码格式、OOP原则,如重写方法、可变参数、过时方法处理。同时,涵盖了集合处理的注意事项,如集合判空、转换数组的方法,以及并发处理中的线程池和锁的使用策略。此外,还强调了日期格式和获取当前时间的规范。
摘要由CSDN通过智能技术生成

第 1 章 编程规约

1.1 命名风格

【强制】 代码中的命名均不能以 _ 或 $ 开始和结束
【强制】 包名统一使用小写,点分隔符之间有且仅有一个自然语义的英语单词,包名统一使用单数形式
com.alibaba.ai.util
【强制】 类名可以使用复数形式。类名使用 UpperCamelCase 风格,但以下情形例外:

  1. DO:Data Object,数据对象。与数据库表结构一一对应,通过 DAO 层向上传输
  2. BO:Business Object,业务对象。BO 包括了业务逻辑,常常封装了对 DAO、RPC 等的调用
  3. DTO:Data Transfer Object,数据传输对象。通常用于不同服务或服务不同分层之间的数据传输
  4. VO:Value Object,与前端进行交互的 Java 对象
  5. AO: Application Object,应用对象。 在 Web 层与 Service 层之间抽象的复用对象模型
  6. PO:Persistant Object,持久对象。表示数据库中的一条记录映射成的 Java 对象
    JavaServerlessPlatform / UserDO / XmlService

【强制】 常量命名应该全部大写,单词间用下划线隔开,力求语义表达完整清楚,不要嫌名字长
MAX_STOCK_COUNT / CACHE_EXPIRED_TIME
【强制】 方法名、参数名、成员变量、局部变量都统一使用 lowerCamelCase 风格,必须遵从驼峰形式
localValue / getHttpMessage() / inputUserId
【强制】抽象类命名使用 Abstract 或 Base 开头;异常类命名使用 Exception 结尾;测试类命名以它要测试的类的名称开始,以 Test 结尾。
【强制】POJO 类中布尔类型变量都不要加 is 前缀,否则部分框架解析会引起序列化错误
【推荐】在常量与变量的命名时,表示类型的名词放在词尾
startTime / workQueue / nameList / TERMINATED_THREAD_COUNT
【推荐】如果模块、接口、类、方法使用了设计模式,在命名时需体现出具体模式
OrderFactory / LoginProxy / ResourceObserver
【推荐】 接口类中的方法和属性不要加任何修饰符号,并加上有效的注释。尽量不要在接口里定义变量,如果一定要定义变量,肯定是与接口方法相关,并且是整个应用的基础常量
【推荐】 如果是形容能力的接口名称,取对应的形容词为接口名(通常是 –able 的形容词)
AbstractTranslator 实现 Translatable 接口
【推荐】 枚举类名带上 Enum 后缀,枚举成员名称需要全大写,单词间用下划线隔开
枚举名字为 ProcessStatusEnum 的成员名称:SUCCESS / UNKNOWN_REASON
【推荐】 Service / DAO 层方法命名规约:

  1. 获取单个对象的方法用 get 做前缀
  2. 获取多个对象的方法用 list 做前缀,复数形式结尾。如 listObjects
  3. 获取统计值的方法用 count 做前缀
  4. 插入的方法用 save / insert 做前缀
  5. 删除的方法用 remove / delete 做前缀
  6. 修改的方法用 update 做前缀
1.2 常量定义

【强制】不允许任何魔法值(即未经预先定义的常量)直接出现在代码中
【强制】在给 Long 类型变量赋值时,数值后使用大写的 L,小写容易跟数字 1 混淆,造成误解
【推荐】不要使用一个常量类维护所有常量,要按常量功能归类,如缓存相关常量放在类 CacheConsts 下,系统配置相关常量放在类 SystemConfigConsts 下
【推荐】常量的复用层次有五层:跨应用共享常量、应用内共享常量、子工程内共享常量、包内共享常量、类内共享常量。
跨应用共享常量放置在二方库中,通常是 client.jar 中的 constant 目录下。应用内共享常量放置在一方库中,通常是子模块中的 constant 目录下。
【推荐】如果变量值仅在一个固定范围内变化用 enum 类型来定义

1.3 代码格式

【强制】if / for / while / switch / do 等保留字与括号之间都必须加空格
【强制】注释的双斜线与注释内容之间有且仅有一个空格
【强制】单行字符限制不超过 120 个,超过需要换行:

  1. 第二行相对第一行缩进 4 个空格,从第三行开始不再继续缩进
  2. 运算符和下行一起换行
  3. 方法调用的点符号与下行一起换行
  4. 方法调用的多个参数需要换行时,在逗号后面进行
  5. 括号前不换行
    【强制】IDE 的 text file encoding 设置为 UTF-8; IDE 中文件的换行符使用 Unix 格式,不要使用 Windows 格式
    【推荐】不同逻辑、不同语义、不同业务的代码插入一个空行分隔开来提升可读性
1.4 OOP 规约

【强制】所有的重写方法,必须加 @Override 注解
【强制】相同参数类型,相同业务逻辑才可以使用可变参数,避免使用 Object。可变参数必须放在参数列表最后
【强制】不能使用过时的类或方法
【强制】接口过时必须加 @Deprecated 注解,并清晰地注释说明采用的新接口
【强制】所有的 POJO 类属性、RPC 方法的返回值和参数必须使用包装数据类型
【强制】所有的 POJO 类属性、RPC 方法的返回值和参数必须使用包装数据类型定义 DO / DTO / VO 等 POJO 类时,不要设定任何属性默认值
【强制】序列化新增属性时,不要修改 serialVersionUID 字段
【强制】POJO 类必须写 toString 方法。如果继承了另一个 POJO 类,注意在前面加一下 super.toString。在方法执行抛出异常时,可以直接调用 POJO 的 toString()方法打印其属性值,便于排查问题。
【强制】比较对象使用 Objects 的 equals 方法
Objects.equals(“test”, object)
【强制】所有整型包装类对象之间值的比较,全部使用 equals 方法比较
【强制】浮点数之间的等值判断,基本数据类型不能用 == 来比较,包装数据类型不能用 equals 来判断,应该指定一个误差范围,两个浮点数的差值在此范围之内,则认为是相等的:

float a = 1.0f - 0.9f;
float b = 0.9f - 0.8f;
float diff = 1e-6f; 
if (Math.abs(a - b) < diff) { 
    System.out.println("true");
 }

或者使用 BigDecimal 来定义值,再进行浮点数的运算操作:

BigDecimal a = BigDecimal.valueOf(1.0);
BigDecimal b = BigDecimal.valueOf(0.9);
BigDecimal c = BigDecimal.valueOf(0.8); 
BigDecimal x = a.subtract(b);
BigDecimal y = b.subtract(c); 
if (x.equals(y)) { 
    System.out.println("true");
}

【推荐】getter / setter 方法中不要增加业务逻辑,setter 方法中 this.成员名=参数名 二者名称一致
【推荐】循环体内,字符串的连接方式,使用 StringBuilder 的 append 方法进行扩展

1.5 集合处理

【强制】只要重写 equals,就必须重写 hashCode。尤其是 Set 集合存储不重复对象,必须重写这两种方法。String 已覆写 hashCode 和 equals 方法,所以我们可以愉快地使用 String 对象作为 key 来使用
【强制】集合判空使用 isEmpty() 方法
【强制】ArrayList 的 subList 不可强转成 ArrayList,因为 subList 返回的并不是 ArrayList,而是 ArrayList 的一个视图
【强制】使用 Map 的方法 keySet() / values() / entrySet() 返回集合对象时,不可以对其进行添加元素操作,否则会抛出 UnsupportedOperationException 异常
【强制】使用集合转数组的方法,必须使用集合的 toArray(T[] array),传入的是类型完全一致、长度为 0 的空数组:
List list = new ArrayList<>(2);
list.add(“guan”);
list.add(“bao”);
String[] array = list.toArray(new String[0]);
【强制】使用工具类 Arrays.asList() 把数组转换成集合时,不能使用其修改集合相关的方法。因为 Arrays.asList 的返回对象是一个 Arrays 内部类,并没有实现集合的修改方法。Arrays.asList 体现的是适配器模式,只是转换接口,后台的数据仍是数组。
【强制】不要在 foreach 循环里进行元素的 remove / add 操作。请使用 Iterator 方式来 remove 元素,如果并发操作,需要对 Iterator 对象加锁:

List<String> list = new ArrayList<>(); 
list.add("1"); 
list.add("2"); 
Iterator<String> iterator = list.iterator(); 
while (iterator.hasNext()) { 
    String item = iterator.next(); 
    if (Objects.equals(item, "1")) {
         iterator.remove(); 
     } 
 }

【强制】HashMap 使用 HashMap(int initialCapacity) 初始化。initialCapacity = (需要存储的元素个数 / 负载因子) + 1,负载因子默认为 0.75。如果暂时无法确定初始值大小,请设置为 16(即默认值)。

1.6 并发处理

【强制】线程资源必须通过线程池提供,不允许在应用中自行显式创建线程
【强制】线程池不允许使用 Executors 去创建,而是通过 ThreadPoolExecutor 的方式
【强制】必须回收自定义的 ThreadLocal 变量,尤其在线程池场景下,线程经常会被复用,如果不清理自定义的 ThreadLocal 变量,可能会影响后续业务逻辑和造成内存泄露等问题。尽量在代理中使用 try-finally 块进行回收:

ThreadLocal.set(userInfo);
try { 
    // ...
} finally { 
     objectThreadLocal.remove();
}

【强制】高并发时,同步调用应该去考量锁的性能损耗。能用无锁数据结构,就不要用锁;能锁区块,就不要锁整个方法体;能用对象锁,就不要用类锁
【强制】对多个资源、数据库表、对象同时加锁时,需要保持一致的加锁顺序,否则可能会造成死锁
【强制】资金相关的金融敏感信息,使用悲观锁策略

1.7 日期事件

【强制】日期格式化年份统一使用小写 y
【强制】获取当前毫秒数使用 System.currentTimeMillis()

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值