Java 开发规范(Android)

Java开发规范

1.命名风格

  1. 参数名,变量名以小驼峰lowerCamelCase规范:profileName
  2. 类名以大驼峰UpperCamelCase规范:UserDO
  3. 常量名大写,单词下划线隔开MAX_STOCK_COUNT
  4. 使用英文命名,不能出现拼音,以最为准确的翻译为准.
  5. 抽象类使用Abstract或者Base开头,异常类使用Exception结束
  6. 数组使用类型[] 变量名方式:String[] names,而不是String args[]
  7. 包名使用小写,不加下划线.
  8. 除了通用缩写方式,尽量使用完整单词组合命名.通用缩写见下表.
  9. 不能出现int a这样的"未知"变量名,必须使用一个可以表达含义的单词或短语.
  10. 接口中的方法和变量不加修饰符(方法默认public abstract,变量默认public static final)
  11. 当使用设计模式时,推荐类名使用设计模式名OrderFactory,LoginProxy,DataObserver
  12. 业务类接口以I开头IPresenter,实现以ImplLoginPresenterImpl结尾.
  13. 枚举类以Enum结尾.枚举成员大写加下划线分隔.
  14. 方法命名规范:
    (1). 获取单个对象以get做前缀
    (2). 获取多个对象以list做前缀,复数形式结尾: listBooks
    (3). 获取统计值用count做前缀
    (4). 插入方法以save/insert做前缀
    (5). 删除方法以remove/delete做前缀
    (6). 修改方法以update做前缀
  15. 领域对象命名规范:
    (1). 数据库对象xxxDO
    (2). 页面展示对象xxxVO
    (3). 上传接口对象xxxReq
    (4). 接口获取对象xxxRes
    (5). 业务对象xxxBO

2.常量定义

  1. 在long或Long类型赋值时,数值使用大写L,而不是小写l,小写l容易和1混淆
  2. 常量类需要按功能分类,不能使用大而全的常量类.例:缓存使用CacheConsts,配置使用ConfigConsts
  3. 如果变量值仅在较小规模的固定范围内变化,使用enum,如季节,星期,生命周期,业务状态等.

3.代码格式

  1. 文件编码使用UTF-8,IDEA设置:
    (1). Preference->Editor->Code Style-> File Encodings "Global Encoding","Project Encoding","Default encoding for properties files"都设置为"UTF-8"UTF-8"
    (2). "Create UTF-8 files"设置为"with No BOM"
  2. 空格使用Unix格式,IDEA设置:
    Preference->Editor->Code Style-> Line separator设置为"Unix and OS X (\n)
  3. 必须使用4个空格缩进,不能使用Tab,IDEA设置:
    Preference->Editor->Code Style->Java -> Tabs and Indents -> "Tab size"和"Indent"设置为4,勿勾选"Use tab character"
  4. 每行超出120个字符换行,换行规则:
    (1). 换行缩进4个空格,再换行不再缩进
    (2). 运算符和下文一起换行
    (3). 方法调用的.与方法一起换行
    (4). 方法内多参数需换行时,在逗号后换行
    IDEA设置:
    (1). Preference->Editor->Code Style-> Hard wrap at 设置为120
    (2). Preference->Editor->Code Style->Java ->Wrapping and Braces -> 勾选"Line breaks"和"Ensure right margin is not exceeded"
  5. 方法内部不同逻辑,不同语义,不同业务之间可以使用换行,代码任意位置不能出现多余1行的空行.IDEA设置:
    Preference->Editor->Code Style->Java->Blank Lines->所有超过1的选项设置为1.
  6. 空格使用规范:
    (1). if/for/while/switch/do 等保留字与括号之间都必须加空格。
    (2). 小括号内左右第一个字符和小括号间不留空格
    (3). 左大括号前加空格
    (4). 二目三目运算符的左右两边都要加空格
    (5). 双斜线和注释内容间仅使用一个空格
    (6). 方法参数间使用一个空格
  7. 大括号使用规范:
    (1). 左大括号前不换行
    (2). 左大括号后换行
    (3). 右大括号前有else等不换行
    (4). 右大括号表示终止需换行
    (5). 大括号内为空,可写成{},并不换行
  8. 推荐单个方法勿超过80行,超过80行考虑提取方法,保持单一责任原则.

4. OOP 规约

  1. 所有静态变量,常量,方法,都使用类名调用,勿使用对象调用.避免增加编译器解析成本.
  2. 所有覆写方法,需要加上@Override注解,避免方法名写错,编译时不报错.推荐使用快捷键调用"Override Members"覆写方法,避免出错.
  3. 避免使用Object作为参数,尽量不适用可变参数.
  4. 不能使用过时的类或方法.
  5. Object的equals方法容易抛空指针异常,应使用常量来调用equals:"cache".equals(xxx),或者使用Objects.equals(a,b)
  6. POJO类属性强制使用包装数据类型,如当数据库查询时结果可能为null,使用基本数据类型去接收会有NPE风险.并且基本数据类型的默认值可能会带来错误信息,比如当调用接口没有返回值时,默认的0,false等会带来歧义.null值表示出额外的信息:调用失败,服务器未返回该值等.
  7. 构造方法里不能加入业务逻辑,初始化逻辑应放在init方法中.
  8. POJO类必须重写toString()方法(Kotlin的data类默认已添加该方法,无需手动添加)
  9. 重载方法应按顺序放在一起,构造方法相同.在此基础上的方法置放顺序:public,proteced > private > getter/setter
  10. getter/setter方法应保持简单的get/set动作,不应插入业务逻辑.
  11. 循环体内,字符串的连接使用StringBuilder的append方法,使用字符串直接+连接会造成每次循环new出StringBuilder对象.(Kotlin可使用"${var1}var2"方式连接)
  12. 方法,属性权限应给满足使用的最小权限.
    (1). 类内使用:private
    (2). 包内和子类使用:protected.
    过于宽泛的权限会导致不当调用泛滥,不利于解耦.(一旦在其他地方被调用,这个方法,属性就不止属于类自己了)
  13. 不能再foreach循环里进行元素的remove/add操作.可能会引起运行时异常.
  14. 为了降低记忆负担,Map中不要使用null作为key,只有HashMap和TreeMap可以存储null的value.
  15. 合理利用好集合的有序性(sort)和稳定性(order),避免集合的无序性(unsort)和
    不稳定性(unorder)带来的负面影响。
    有序性是指遍历的结果是按某种比较规则依次排列的。稳定性指集合每次遍历的元素次
    序是一定的。如:ArrayList 是 order/unsort;HashMap 是 unorder/unsort;TreeSet 是order/sort。
  16. 可以用用Set的唯一性快速去重,不要使用List的contains方法进行遍历对比去重.
  17. 表达异常的分支,少用if-else,减少if-else嵌套,嵌套不能超过3层,消灭箭头语句,尽量使用卫语句(剪枝逻辑):
No:

if(condition1){
    
} esle if(condition2) {
    
} else if(condition3) {
    
}

Yes:

if(condition1){
    
}
if(condition2){
    
}
if(condition3){
    
}
  1. 不要直接使用复杂的判断逻辑,将复杂的判断表达式赋值给一个有意义的布尔变量,调代码可读性.
正例:
// 伪代码如下
final boolean existed = (file.open(fileName, "w") != null) && (...) || (...);
if (existed) {
 ...
}
反例:
if ((file.open(fileName, "w") != null) && (...) || (...)) {
 ...
}
  1. 校验参数规范:
    (1). 执行流程较为复杂的方法需要进行参数校验(FastFail)
    (2). 与用户输入相关方法需校验参数.
    (3). 对外提供的开放接口需校验参数.
    (4). 较为底层且调用次数频繁方法不需要校验参数.

5. 注释规约

  1. 类、类属性、类方法的注释必须使用 Javadoc 规范,使用/*内容/格式,不得使用
    // xxx 方式。
    说明:在 IDE 编辑窗口中,Javadoc方式会提示相关注释,生成Javadoc可以正确输出相应注释;在IDE中,工程调用方法时,不进入方法即可悬浮提示方法、参数、返回值的意义,提高阅读效率。
  2. 所有的抽象方法(包括接口中的方法)必须要用Javadoc注释、除了返回值、参数、异常说明外,还必须指出该方法做什么事情,实现什么功能。
    说明:对子类的实现要求,或者调用注意事项,需一并说明。
  3. 方法内部单行注释,在被注释语句上方另起一行,使用//注释。方法内部多行注释
    使用/* */注释,注意与代码对齐。
  4. 注释掉的代码用注释说明注释原因,注释原因用///注释,如果不再使用,删除该代码,使用版本控制追溯.
  5. 对于注释的要求:
    (1). 能够准确反应设计思想和代码逻辑
    (2). 能够描述业务含义,使别的程序员能够迅速了解到代码背后的信息。
    (3). 保持和代码的同步.
    (4). 尽量使用常用,简单的英语进行注释.可搭配翻译使用,避免中式英语.
    (5). 使用最简练的语言写注释,好的命名、代码结构是自解释的,避免过多过滥的注释.
反例:
// put elephant into fridge
put(elephant, fridge);
方法名 put,加上两个有意义的变量名 elephant 和 fridge,已经说明了这是在干什么,语
义清晰的代码不需要额外的注释。
  1. 特殊注释标记
    (1). 待办事宜(TODO):( 标记人,标记时间,[预计处理时间])
    (2). 错误,不能工作(FIXME):(标记人,标记时间,[预计处理时间])

6. 异常处理规约

  1. 异常因使用最小粒度进行捕获,不能使用一个exception进行捕获.注意多个异常排列的顺序.
  2. 捕获异常应尽量catch最小的单元,不要catch过多内容.
  3. 捕获异常之后必须处理.推荐异常进行日志记录上报(Do not swallow)
  4. 资源需要在finally中释放,推荐使用try-with-resource的方式.
  5. 级联调用 obj.getA().getB().getC();一连串调用,易产生 NPE。使用 JDK8 的 Optional 类来防止 NPE 问题。(Kotlin可使用?.调用方式处理)
if(obj == null){
  return;
}
if(a == null){
  return;
}
if(b == null){
  return;
}
b.getC();

if(obj?.getA()?.getB()?.getC() == null){
  return
}

obj!!.getA();

7. 日志规约

  1. 日志文件至少保存15天,有些异常是以"周"为频次发生的.
  2. 对 trace/debug/info 级别的日志输出,必须使用条件输出形式或者使用占位符的方
    式。
反例
logger.debug("Processing trade with id: " + id + " and symbol: " + symbol);

正例:(条件)建设采用如下方式
if (logger.isDebugEnabled()) {
logger.debug("Processing trade with id: " + id + " and symbol: " + symbol);
}

正例:(占位符)
logger.debug("Processing trade with id: {} and symbol : {} ", id, symbol); 

Kotlin中可采取
logger.debug("Processing trade with id: ${id} and symbol: ${symbol}");
  1. 日志不可重复打印,冗余打印,保持精简.
  2. 异常日志应记录必要的现场信息和堆栈信息
正例:
logger.error(各类参数或者对象 toString() + "_" + e.getMessage(), e);
  1. 生产环境应关闭debug日志.(远程调试除外)

讨论

  1. 所有的枚举类型字段必须要有注释,说明每个数据项的用途。
  2. 每个switch需要带上default,case语句如果没有break语句,需要在末尾注释// fall down

TODO:单元测试规约

参考:
阿里巴巴java开发手册
插件使用文档
阿里巴巴Android开发手册

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,684评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,143评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,214评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,788评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,796评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,665评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,027评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,679评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,346评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,664评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,766评论 1 331
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,412评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,015评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,974评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,073评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,501评论 2 343

推荐阅读更多精彩内容