JAVA编码规约(阿里)

java开发规范(阿里)
1、抽象类命名使用 Abstract 或 Base 开头;异常类命名使用 Exception 结尾;测试类 命名以它要测试的类的名称开始,以 Test 结尾
2、如果使用到了设计模式,建议在类名中体现出具体模式。 说明:将设计模式体现在名字中,有利于阅读者快速理解架构设计思想。 
  正例:public class OrderFactory;
        public class LoginProxy;
         public class ResourceObserver
3、 接口和实现类的命名有两套规则:  
    1)【强制】对于 Service 和 DAO 类,基于 SOA 的理念,暴露出来的服务一定是接口,内部 的实现类用 Impl 的后缀与接口区别。 正例:CacheServiceImpl 实现 CacheService 接口。  
    2)【推荐】 如果是形容能力的接口名称,取对应的形容词做接口名(通常是–able 的形式)。 正例:AbstractTranslator 实现 Translatable。 
4、枚举类名建议带上 Enum 后缀,枚举成员名称需要全大写,单词间用下划线隔开。 说明:枚举其实就是特殊的常量类,且构造方法被默认强制是私有。  
  正例:枚举名字:DealStatusEnum,成员名称:SUCCESS / UNKOWN_REASON
5、各层命名规约:  
    A) Service/DAO 层方法命名规约    
        1) 获取单个对象的方法用 get 做前缀。    
        2) 获取多个对象的方法用 list 做前缀。    
        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。 
        
6、不允许出现任何魔法值(即未经定义的常量)直接出现在代码中。  反例: String key="Id#taobao_"+tradeId;         cache.put(key, value); 
7、long 或者 Long 初始赋值时,必须使用大写的 L,不能是小写的 l,小写容易跟数字 1 混淆,造成误解。 说明:Long a = 2l; 写的是数字的 21,还是 Long 型的 2? 
8、不要使用一个常量类维护所有常量,应该按常量功能进行归类,分开维护。如:缓存 相关的常量放在类:CacheConsts 下;系统配置相关的常量放在类:ConfigConsts 下。 说明:大而全的常量类,非得使用查找功能才能定位到修改的常量,不利于理解和维护。 
9、常量的复用层次有五层:跨应用共享常量、应用内共享常量、子工程内共享常量、包 内共享常量、类内共享常量。  1) 跨应用共享常量:放置在二方库中,通常是 client.jar 中的 constant 目录下。  2) 应用内共享常量:放置在一方库的 modules 中的 constant 目录下。   反例:易懂变量也要统一定义成应用内共享常量,两位攻城师在两个类中分别定义   了 表示“是”的变量:     类 A 中:public static final String YES = "yes";     类 B 中:public static final String YES = "y";     A.YES.equals(B.YES),预期是 true,但实际返回为 false,导致产生线上问题。  
 3) 子工程内部共享常量:即在当前子工程的 constant 目录下。  4) 包内共享常量:即在当前包下单独的 constant 目录下。  5) 类内共享常量:直接在类内部 private static final 定义。 
10、如果变量值仅在一个范围内变化用 Enum 类。如果还带有名称之外的延伸属性,必须 使用 Enum 类,下面正例中的数字就是延伸信息,表示星期几。 正例:public Enum{ MONDAY(1), TUESDAY(2), WEDNESDAY(3), THURSDAY(4), FRIDAY(5), SATURDAY(6), SUNDAY(7);} 
11、关于基本数据类型与包装数据类型的使用标准如下:  1) 所有的 POJO 类属性必须使用包装数据类型。  2) RPC 方法的返回值和参数必须使用包装数据类型。  3) 所有的局部变量【推荐】使用基本数据类型。 
12、定义 DO/DTO/VO 等 POJO 类时,不要设定任何属性默认值。 反例:POJO 类的 gmtCreate 默认值为 new Date();但是这个属性在数据提取时并没有置入具 体值,在更新其它字段时又附带更新了此字段,导致创建时间被修改成当前时间。 
13、setter 方法中,参数名称与类成员变量名称一致,this.成员名=参数名。在 getter/setter 方法中,尽量不要增加业务逻辑,增加排查问题的难度。 反例: public Integer getData(){      if(true)  {  return data + 100;  } else  { return data - 100; }  }  
14、循环体内,字符串的联接方式,使用 StringBuilder 的 append 方法进行扩展。 反例: String str = "start";      for(int i=0; i<100; i++){          str = str + "hello";      }  说明:反编译出的字节码文件显示每次循环都会 new 出一个 StringBuilder 对象,然后进行 append 操作,最后通过 toString 方法返回 String 对象,造成内存资源浪费
15、final 可提高程序响应效率,声明成 final 的情况:  1) 不需要重新赋值的变量,包括类属性、局部变量。  2) 对象参数前加 final,表示不允许修改引用的指向。  3) 类方法确定不允许被重写。 
16、使用集合转数组的方法,必须使用集合的 toArray(T[] array),传入的是类型完全 一样的数组,大小就是 list.size()。 反例:直接使用 toArray 无参方法存在问题,此方法返回值只能是 Object[]类,若强转其它 类型数组将出现 ClassCastException 错误。 正例: List<String> list = new ArrayList<String>(2);      list.add("guan");      list.add("bao");       String[] array = new String[list.size()];      array = list.toArray(array);  说明:使用 toArray 带参方法,入参分配的数组空间不够大时,toArray 方法内部将重新分配 内存空间,并返回新数组地址;如果数组元素大于实际所需,下标为[ list.size() ]的数组 元素将被置为 null,其它数组元素保持原值,因此最好将方法入参数组大小定义与集合元素 个数一致。 
17、不要在 foreach 循环里进行元素的 remove/add 操作。remove 元素请使用 Iterator 方式,如果并发操作,需要对 Iterator 对象加锁。 反例: List<String> a = new ArrayList<String>();      a.add("1");      a.add("2");      for (String temp : a) {          if("1".equals(temp)){              a.remove(temp);          }      }  
说明:以上代码的执行结果肯定会出乎大家的意料,那么试一下把“1”换成“2”,会是同样的 结果吗? 正例: Iterator<String> it = a.iterator();  while(it.hasNext()){              String temp =  it.next();                       if(删除元素的条件){                              it.remove();                 }      } 
18、集合初始化时,尽量指定集合初始值大小。 说明:ArrayList 尽量使用 ArrayList(int initialCapacity) 初始化。 
19、使用 entrySet 遍历 Map 类集合 KV,而不是 keySet 方式进行遍历。 说明:keySet 其实是遍历了 2 次,一次是转为 Iterator 对象,另一次是从 hashMap 中取出 key 所对应的 value。而 entrySet 只是遍历了一次就把 key 和 value 都放到了 entry 中,效 率更高。如果是 JDK8,使用 Map.foreach 方法。 正例:values()返回的是 V 值集合,是一个 list 集合对象;keySet()返回的是 K 值集合,是 一个 Set 集合对象;entrySet()返回的是 K-V 值组合集合。 
20、创建线程或线程池时请指定有意义的线程名称,方便出错时回溯。 正例: public class TimerTaskThread extends Thread {      public TimerTaskThread(){          super.setName("TimerTaskThread");  ...  }  
21、线程资源必须通过线程池提供,不允许在应用中自行显式创建线程。 说明:使用线程池的好处是减少在创建和销毁线程上所花的时间以及系统资源的开销,解决资
源不足的问题。如果不使用线程池,有可能造成系统创建大量同类线程而导致消耗完内存或者 “过度切换”的问题。 
22、】线程池不允许使用 Executors 去创建,而是通过 ThreadPoolExecutor 的方式,这样 的处理方式让写的同学更加明确线程池的运行规则,规避资源耗尽的风险。 说明:Executors 返回的线程池对象的弊端如下: 
1)FixedThreadPool 和 SingleThreadPool:   允许的请求队列长度为 Integer.MAX_VALUE,可能会堆积大量的请求,从而导致 OOM。 2)CachedThreadPool 和 ScheduledThreadPool:   允许的创建线程数量为 Integer.MAX_VALUE,可能会创建大量的线程,从而导致 OOM。 
23、SimpleDateFormat 是线程不安全的类,一般不要定义为 static 变量,如果定义为 static,必须加锁,或者使用 DateUtils 工具类。 正例:注意线程安全,使用 DateUtils。亦推荐如下处理: private static final ThreadLocal<DateFormat> df = new ThreadLocal<DateFormat>() {        @Override        protected DateFormat initialValue() {            return new SimpleDateFormat("yyyy-MM-dd");        }    };    说明:如果是 JDK8 的应用,可以使用 Instant 代替 Date,LocalDateTime 代替 Calendar, DateTimeFormatter代替Simpledateformatter,官方给出的解释:simple beautiful strong immutable thread-safe。 
24、对多个资源、数据库表、对象同时加锁时,需要保持一致的加锁顺序,否则可能会造 成死锁。 说明:线程一需要对表 A、B、C 依次全部加锁后才可以进行更新操作,那么线程二的加锁顺序 也必须是 A、B、C,否则可能出现死锁。 
25、在一个 switch 块内,每个 case 要么通过 break/return 等来终止,要么注释说明程 序将继续执行到哪一个 case 为止;在一个 switch 块内,都必须包含一个 default 语句并且 放在最后,即使它什么代码也没有。 
26、推荐尽量少用 else, if-else 的方式可以改写成: 
if(condition){              ...             return obj;    }   // 接着写 else 的业务逻辑代码;  说明:如果非得使用 if()...else if()...else...方式表达逻辑,【强制】请勿超过 3 层, 超过请使用状态设计模式。  正例:逻辑上超过 3 层的 if-else 代码可以使用卫语句,或者状态模式来实现。 
27、表必备三字段:id, gmt_create, gmt_modified。 说明:其中 id 必为主键,类型为 unsigned bigint、单表时自增、步长为 1。gmt_create, gmt_modified 的类型均为 date_time 类型。 
28、单表行数超过 500 万行或者单表容量超过 2GB,才推荐进行分库分表。 说明:如果预计三年后的数据量根本达不到这个级别,请不要在创建表时就分库分表。 
 

转载于:https://my.oschina.net/chuibilong/blog/857451

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值