【强制】 源文件应以其最顶层的类名来命名,区分大小写,文件扩展名为.java
[1]。
【强制】 一个源文件应包含[1]:
说明:按顺序,每个部分之间用一个空行隔开。
许可证或版权信息(如有需要);
package
语句;
import
语句;
一个顶级类(仅有一个).
【强制】 许可证和版权信息应放在文件的最前面[1]
规范1-3正确示例
/**
* Copyright (C),2002-2018, 苏宁软件技术有限公司
* Author: 边涛
* Date: 2018年7月15日 下午2:16:23
* Description: 测试文件
*/
package com.bt.hub.myhub;
import android.app.Activity;
import android.os.Bundle;
public class TestActivity extends Activity{
...
}
【强制】 package
语句应写在一行不换行,列限制不适用于package
语句[1]
. 【强制】 import
语句应写在一行不换行,列限制不适用于import
语句[1]。
【强制】 import
语句不使用通配符[1]
规范4-6示例
// 反例
import com.bt.hub.myhub.
Carousel.adapter.CarouselAdapter;
import com.bt.hub.myhub.
Carousel.view.CarouselView;
import com.bt.hub.myhub.R;
import java.util.*;
// 正例
import com.bt.hub.myhub.Carousel.adapter.CarouselAdapter;
import com.bt.hub.myhub.Carousel.view.CarouselView;
import com.bt.hub.myhub.R;
import java.util.ArrayList;
import java.util.List;
【强制】 import
语句可以分为以下几组[1]:
说明:按顺序,每个部分之间用一个空行隔开,所有的静态导入独立成组,每个顶级包为一组,组内不空行,按字典序排列。
com.google
的包(仅当这个源文件是在com.google
包下);规范正确示例
// 包名
package com.suning.mobile.epa.zxing.encoding;
// com.google的包
import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.WriterException;
import com.google.zxing.common.BitMatrix;
// android包
import android.graphics.Bitmap;
// java包
import java.util.Hashtable;
import java.util.ArrayList;
【强制】 类声明每个顶级类都在一个与它同名的源文件中(当然,还包含.java
后缀)[1]。
【强制】 每个类应该以某种逻辑去排序它的成员,维护者应该要能解释这种排序逻辑[1]。
说明:类的成员顺序对程序易读性有很大的影响,但这也不存在唯一的通用法则。不同的类对成员的排序可能是不同的。新的成员不能总是习惯性地依次添加到前者后面,因为这样就是按时间顺序而非某种逻辑来排序的。
【强制】 建议使用注释将源文件分为明显的区块,区块划分如下:
说明:对源文件进行分区,可以方便快捷的进行代码定位,提高阅读效率。
get
/set
方法区;【强制】 类成员组织通用规则[1]:
layout
布局文件的先后顺序排列;【强制】 重载永不分离[1]。
说明:当一个类有多个构造函数,或是多个同名方法,这些函数/方法应该按顺序出现在一起,中间不要放进其它函数/方法。
规范9-12正确示例:
public class CarouselMainActivity extends Activity implements View.OnClickListener {
/*
* 常量
* /
private static final String TAG = "CarouselMainActivity";
/*
* UI变量
* /
private CarouselView mCarouselView;
private CarouselAdapter mCarouselAdapter;
/*
* 普通
* /
private List mModel = new ArrayList<>();
/*
* 生命周期
* /
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.carousel_main_layout);
initView();
initData(4);
}
@Override
protected void onResume() {...}
/*
* 自定义方法
* /
private void initView() {...}
private void initData(int num) {...}
/*
* 接口实现
* /
@Override
public void onClick(View v) {...}
/*
* 内部类
* /
public class Page {...}
}
【强制】 代码中的命名均不能以下划线_
或美元符号$
开始,也不能以下划线_
或美元符号$
结束[2] 。
规范错误示例
// 反例
private String _name;
private String __name;
private String name_;
private String $Object;
private String name$;
private String Object$;
【强制】 代码中的命名严禁使用拼音与英文混合的方式,更不允许直接使用中文的方式[2] 。
说明:正确的英文拼写和语法可以让阅读者易于理解,避免歧义。注意,即使纯拼音命名方式也要避免采用。
规范示例
// 国际通用的命名,例如suning/nanjing等可以使用拼音
public String suningName = "suning";
public String nanjingName = "nanjing";
// 反例,用于表示圆点是否显示
public String dianShow;
public String dianHide;
// 正例,必须使用英文
public String dotShow;public String dotHide;
【推荐】 如果模块、接口、类、方法使用了设计模式,在命名时要体现出具体模式[2]
说明:将设计模式体现在名字中,有利于阅读者快速理解架构设计理念。
规范正确示例
public class OrderFactory;
public class LoginProxy;
public class ResourceObserver;
【强制】 中括号[]
是数组类型的一部分,数组定义如下[2]:
规范示例
//正例
String[] args
//反例
String args[]
【推荐】 为了达到代码自解释的目标,任何自定义编程元素在命名时,使用尽量完整的单词组合来表达其意[2]。
规范示例
// 正例 从远程仓库拉取代码
public class PullCodeFromRemoteRepository{}
// 反例 不知其义的命名
public int a;
【推荐】 接口类中的方法和属性不要加任何修饰符号(public
也不要加),保持代码的简洁性,并加上有效的Javadoc 注释。尽量不要在接口里定义变量,如果一定要定义变量,肯定是与接口方法相关,并且是整个应用的基础常量[2]
说明:JDK 8 中接口允许有默认实现,那么这个default
方法,是对所有实现类都有价值的默认实现。
规范示例
// 反例
public interface CarouselButtonClickListener{
public String COMPANY = "suning";
public abstract void onLeftBtnClick();
public abstract void onRightBtnClick();
}
// 正例
public interface CarouselButtonClickListener{
String COMPANY = "suning";
void onLeftBtnClick();
void onRightBtnClick();
}
【强制】 包名统一使用小写,必须遵从。
规范示例
// 正例
com.suning.mobile.epa.util
com.suning.mobile.epa.common
// 反例
com.suning.mobile.epa.Util
com.suning.mobile.epa.Common
【强制】 连续的单词只是简单的连接起来,不使用下划线。
规范示例
// 正例
com.suning.mobile.epa.commonutil
// 反例
com.suning.mobile.epa.commonUtil
com.suning.mobile.epa.Common_Util
【强制】 点分隔符之间有且仅有一个自然语义的英语单词。
规范示例
// 正例
com.suning.mobile.epa.activity.message.commonutil
// 反例
com.suning.mobile.epa.activitymessagecommonutil
【强制】 包名采用反域名命名规则,一级包名为com / cn / net
,二级包名可以为个人/公司的名字,三级包名根据应用名称进行命名,四级包名为模块名或层级名。
【强制】 包名统一使用单数形式,但是类名如果有复数含义,类名可以使用复数形式。
规范示例
// 正例 包名
com.suning.epamobile.util
// 正例 类名
MessageUtils
//反例 包名
com.suning.epamobile.utils
【强制】 一般情况下,包名可以按照层级划分;而对于比较大的项目,也可以按照业务来划分,便于单独某个业务的管理。
说明 |
---|
m.company.appnameabbr.activity |
m.company.appnameabbr.fragment |
m.company.appnameabbr.model |
m.company.appnameabbr.presenter |
m.company.appnameabbr.adapter |
m.company.appnameabbr.service |
m.company.appnameabbr.receiver |
m.company.appnameabbr.provider |
m.company.appnameabbr.util |
m.company.appnameabbr.ui |
m.company.appnameabbr.base |
m.company.appnameabbr.db |
【强制】 类名使用大驼峰形式UpperCamelCase 风格,必须遵从。
规范示例
// 正例
public class XmlService{}
public class TcpUdpDeal{}
// 反例
public class XMLService{}
public class XmlSeTCPUDPDealrvice{}
【推荐】 尽量避免缩写,除非该缩写是众所周知的。
规范示例
//反例 point
public String poi;
//反例 dateformat
public String df;
//正例 message
public String msg;
//正例 background
public String bg;
【推荐】 类名通常是名词或名词短语,接口名称有时可能是形容词或形容词短语,现在还没有特定的规则或行之有效的约定来命名注解类型。
规范示例
//反例
public class Query{};
public interface User{};
//正例
public class MessageDao{};
public interface UserDataChanged{};
【推荐】 特定类型的子类需要使用统一的前缀/后缀
说明 | 举例 |
---|---|
tivity 类 | 使用 Activity 为后缀 |
agment 类 | 使用 Fragment 为后缀 |
del 模型类 | 使用 Model 为后缀 |
esenter 类 | 使用 Presenter 为后缀 |
apter 适配器类 | 使用 Adapter 为后缀 |
rvice 类 | 使用 Service 为后缀 |
oadcastReceiver 类 | 使用 Receiver 为后缀 |
ntentProvider | 使用 Provider 为后缀 |
方法类 | 使用 Utils / Managers 为后缀 |
义控件类 | 使用 View 或者其继承的父类为后缀 |
类 | 使用 Parser 为后缀 |
库类 | 使用 SqliteOpenHelper 为后缀 |
义的共享基础类 | 使用 Base 为前缀 |
类 | 使用 Abstract 为前缀 |
类 | 使用它要测试的类名为前缀,以 Test 为后缀 |
类 | 使用 Exception 为后缀 |
类 | 多以 I / On 为前缀,以 able / ible /Listener 为后缀 |
【参考】 枚举类名建议带上Enum后缀,枚举成员名称需要全大写,单词间用下划线隔开 [2] 。
规范示例
// 反例
public enum ProcessStatus{
success, unKnowREASON;
}
// 正例
public enum ProcessStatusEnum{
SUCCESS, UNKNOW_REASON;
}
【强制】 方法名使用小驼峰形式 lowerCamelCase 风格,必须遵从。
规范示例
// 正例
getHttpMessage()
// 反例
GetHttpMessage()
【推荐】 方法名通常是动词或动词短语。
【推荐】 通常特定的方法会使用约定俗成的单词
法名 | 说明 |
---|---|
nitXX() | 初始化相关的方法,使用 init 为前缀 |
sXX() / checkXX() | 方法返回值为 boolean 型的方法,使用 is / check 为前缀 |
etXX() | 返回某个值、获取单个对象的方法,使用 get 为前缀 |
aveXX() / insertXX() | 数据库插入的方法,使用 save / insert 为前缀 |
emoveXX() / deleteXX() | 数据库删除的方法,使用 remove / delete 为前缀 |
pdateXX() | 数据库修改的方法,使用 update 为前缀 |
ueryXX() | 数据库查询的方法,使用 query 为前缀 |
aveXX() | 保存数据相关的方法,使用 save 为前缀 |
esetXX() | 数据重组、恢复初始状态的方法,使用 reset 为前缀 |
learXX() | 清空相关的方法,使用 clear 为前缀 |
andleXX() / processXX() | 处理相关的方法,尽量使用 handle / process 为前缀 |
isplayXX() / showXX() | 展示弹窗、提示信息的方法,使用 display / show 为前缀 |
ismissXX() | 销毁弹窗的方法,使用 dismiss 为前缀 |
otoXX() | 跳转的方法,使用 goto 为前缀 |
rawXX() | 绘制相关的方法,使用 draw 为前缀 |
【强制】 参数名、成员变量、局部变量都统一使用小驼峰形式 lowerCamelCase 风格,必须遵从
规范示例
// 正例:
public int localValue;
public int inputUserId;
// 反例:
public int localvalue;
public int input_userId;
【强制】 类中控件名称必须与 xml 布局 id 保持一致。
规范示例
// 正例:
btnCancel = (Button)findViewById(R.id.btn_cancel);
tvTitle = (TextView)findViewById(R.id.tv_title);
// 反例:
cancel = (Button)findViewById(R.id.btn_cancel);
title = (TextView)findViewById(R.id.head);
【推荐】 用统一的量词。
说明:通过在结尾处放置一个量词,就可创建更加统一的变量,它们更容易理解,也更容易搜索。
词后缀 | 说明 |
---|---|
irst | 一组变量中的第一个 |
ast | 一组变量中的最后一个 |
ext | 一组变量中的下一个变量 |
rev | 一组变量中的上一个 |
ur | 一组变量中的当前变量 |
规范示例
// 正例
strCustomerFirst / strCustomerLast
// 反例
strFirstCustomer / strLastCustomer
【推荐】 Activity
中的 View
变量推荐使用View
缩写_逻辑名称的模式。如果布局很复杂,建议将布局分成多个模块,每个模块定义一个moduleViewHolder
,其成员变量包含所属的 View
。
【强制】 常量名统一使用 CONSTANT_CASE 风格,全部大写,单词间用下划线隔开,力求语义表达完整清楚,不要嫌名字长 [2]。
规范示例
// 正例:
MAX_PAGE_COUNT
// 反例:
MAX_COUNT
MAXPAGECOUNT
【强制】 不允许任何魔法值(即未经定义的常量)直接出现在代码中 [2] 。
规范示例
// 反例
if(model.get(i).equals("2")){}
switch (code){
case 1:
...
case 2:
...
}
// 正例
public static final String WEB_TYPE_MESSAGE = "2";
public static final int HOT_CITIES = 1;
public static final int ALL_CITIES = 2;
...
if(model.get(i).equals(WEB_TYPE_MESSAGE)){}
switch (code){
case HOT_CITIES:
...
case ALL_CITIES:
...
}
【强制】 long
或者Long
初始赋值时,值使用大写的L
,不能是小写的l
,小写容易跟数字1
混淆,造成误解[2] 。
规范示例
// 正例:
Long a = 2L;
// 反例:
Long a = 2l;
说明:Long a = 2l;
写的是数字的21
,还是Long型的2
?
【推荐】 不要使用一个常量类维护所有常量,应按常量功能进行归类,分开维护[2] 。
说明:大而全的常量类,非得使用查找功能才能定位到修改的常量,不利于理解和维护。
正例:缓存相关常量放在类CacheConsts
下;系统配置相关常量放在类ConfigConsts
下。
【推荐】 常量的复用层次:应用内共享常量、子工程内共享常量、包内共享常量、类内共享常量[2]。
应用内共享常量:放置在一方库中,通常是modules
中的constant
目录下。
子工程内部共享常量:即在当前子工程的constant
目录下。
包内共享常量:即在当前包下单独的constant
目录下。
类内共享常量:直接在类内部private static final
定义。
规范4-5示例
// 反例
// com.epa.suning.mobile.Constants
public static final int LOGIN_SUCCESS_CODE = 1;
public static final int LOGIN_SUCCESS_CODE = 2;
public static final int HOME_PULL_TO_REFRESH_PULL = 1;
public static final int HOME_PULL_TO_REFRESH_REFRESHING = 2;
public static final int HOME_PULL_TO_REFRESH_DONE = 3;
// 正例
// com.epa.suning.mobile.login.LoginConstants
public static final int LOGIN_SUCCESS_CODE = 1;
public static final int LOGIN_SUCCESS_CODE = 2;
// com.epa.suning.mobile.home.HomeConstants
public static final int HOME_PULL_TO_REFRESH_PULL = 1;
public static final int HOME_PULL_TO_REFRESH_REFRESHING = 2;
public static final int HOME_PULL_TO_REFRESH_DONE = 3;
【推荐】 如果变量值仅在一个范围内变化,且带有名称之外的延伸属性,定义为枚举类。下面正例中的数字就是延伸信息,表示星期几[2] 。
规范示例
public enum WeekEnum {
MONDAY(1), TUESDAY(2), WEDNESDAY(3),
THURSDAY(4), FRIDAY(5), SATURDAY(6), SUNDAY(7);
private int index;
WeekEnum(int idx) {
this.index = idx;
}
public int getIndex() {
return index;
}
}
【强制】 资源文件名统一使用小写,必须遵从。
【强制】 采用下划线命名法,加前缀区分命名模式:activity
名称_逻辑名称 / common
_逻辑名称。
【推荐】 drawable
文件夹中的资源文件的命名规则
文件名 | 说明 |
---|---|
n_xxx | 使用 selector 时不必声明按钮状态 |
n_xxx_normal | 正常情况效果 |
n_xxx_pressed | state_pressed 按下效果 |
n_xxx_focused | state_focused 聚焦效果 |
n_xxx_disabled | state_disabled(false) 不可用效果 |
n_xxx_checked | state_checked 选中效果 |
n_xxx_selected | state_selected 选中效果 |
n_xxx_hovered | state_hovered 悬停效果 |
n_xxx_checkable | state_checkable 可选效果 |
n_xxx_checkable | state_checkable 可选效果 |
n_xxx_activated | state_activated 激活的 |
n_xxx_windowfocused | state_window_focused |
【强制】 资源文件名统一使用小写,必须遵从。
【强制】 采用下划线命名法,加前缀区分命名模式:anim
类型_方向。
【推荐】 anim
文件夹中的动画文件的命名规则
画文件名 | 说明 |
---|---|
ade_in | 淡入 |
ade_out | 淡出 |
ush_down_in | 从下方推入 |
ush_down_out | 从下方推出 |
ush_left | 推向左方 |
lide_in_from_top | 从头部滑动进入 |
oom_enter | 变形进入 |
lide_in | 滑动进入 |
hrink_to_middle | 中间缩小 |
资源文件规范示例
// 反例
activityHome
ActivityLoginSuccess
selected
fade_in
// 正例
activity_home
activity_login_success
btn_select
anim_fadein
【强制】 杜绝完全不规范的缩写,避免望文不知义。
说明:随意缩写会严重降低代码的可阅读性。
正例:
ResponseMessage
缩写命名成RspMsg
ErrorCode
缩写命名成ErrCode
反例:
AbstractClass
缩写命名成AbsClass
condition
缩写命名成condi
【推荐】 日常常用的英文单词缩写
缩写 |
---|
on |
lor |
vider |
lector |
erage |
ckground |
ffer |
ntrol |
lete |
cument |
ror |
cape |
crement |
fomation |
itial |
age |
ternationlization |
ngth |
brary |
ssage |
ssword |
sition |
rver |
ring |
mp |
ndow |
【强制】 Android 常用 View 的英文单词缩写
缩写 |
---|
nearLayout |
lativeLayout |
ameLayout |
bleLayout |
xtView |
ageView |
idView |
itText |
toCompleteTextView |
tton |
ageButton |
ggleButton |
dioButton |
eckBox |
xtSwitch |
ageSwitch |
alogClock |
gtalClock |
tePicker |
mePicker |
ogressBar |
ntingBar |
ekBar |
bView |
pView |
deoView |
rollView |
stView |
pandableList |
b |
ronometer |
inner |
omControls |
【强制】 大括号的使用约定。如果是大括号内为空,则简洁地写成{}即可,不需要换行;如果是非空代码块则:
【强制】 左小括号和字符之间不出现空格;同样,右小括号和字符之间也不出现空格。
正例:if (a == b)
反例:if ( a == b )
【强制】 if / for / while / switch / do / try / catch / synchronized
等保留字与括号之间都必须加空格。
【强制】 任何二目、三目运算符的左右两边都需要加一个空格。
说明:运算符包括赋值运算符=
、逻辑运算符&&
、加减乘除符号等。
【强制】 采用 4 个空格缩进,禁止使用 tab
字符。
说明:如果使用 tab
缩进,必须设置 1 个 tab
为 4 个空格。
IDEA 设置 tab
为 4 个空格时,请勿勾选 Use tab character;而在 eclipse 中,必须勾选 insert spaces for tabs。
规范1-5示例
public static void main(String[] args) {
// 缩进4个空格
String say = "hello";
// 运算符的左右必须有一个空格
int flag = 0;
// 关键词if与括号之间必须有一个空格
// 括号内的f与左括号, 0与右括号不需要空格
if (flag == 0) {
System.out.println(say);
}
// 左大括号前加空格且不换行;左大括号后换行
if (flag == 1) {
System.out.println("world");
// 右大括号前换行,右大括号后有else,不用换行
} else {
System.out.println("ok");
// 在右大括号后直接结束,则必须换行
}
}
【强制】 注释的双斜线与注释内容之间有且仅有一个空格。
规范示例
//这是一个反例注释
/*
这是一个反例注释
*/
/*
*这是一个反例注释
*/
// 这是一个正例注释
/*
* 这是一个反例注释
*/
【强制】 单行字符数限制不超过 120 个,超出需要换行,换行时遵循如下原则:
规范示例
// 正例
StringBuffer sb = new StringBuffer();
// 超过 120个字符的情况下,换行缩进4个空格,点号和方法名称一起换行
sb.append("zi").append("xin")...
.append("huang")...
.append("huang")...
.append("huang");
// 反例
StringBuffer sb = new StringBuffer();
// 超过 120个字符的情况下,不要在括号前换行
sb.append("zi").append("xin")...append
("huang");
// 参数很多的方法调用可能超过120个字符,不要在逗号前换行
method(args1, args2, args3, ...
, argsX);
【强制】 方法参数在定义和传入时,多个参数逗号后边必须加空格。
规范示例
//正例
method("a", "b", "c");
//反例
method("a" ,"b" ,"c");
【强制】 IDE 的 text file encoding 设置为 UTF-8。
【强制】 IDE 中文件的换行符使用 Unix 格式,不要使用 Windows 格式。
【推荐】 没有必要增加若干空格来使某一行的字符与上一行对应位置的字符对齐。
规范示例
//正例
int a = 3;
long b = 4L;
float c = 5F;
StringBuffer stringBuffer = new StringBuffer();
// 反例
int a = 3;
long b = 4L;
float c = 5F;
StringBuffer stringBuffer = new StringBuffer();
说明:增加stringBuffer
这个变量,如果需要对齐,则给a、b、c都要增加几个空格,在变量比较多的情况下,是一种累赘的事情。
【推荐】 方法体内的执行语句组、变量的定义语句组、不同的业务逻辑之间或者不同的语义之间插入一个空行。相同业务逻辑和语义之间不需要插入空行。
说明:没有必要插入多个空行进行隔开。
【强制】 类、类属性、类方法的注释必须使用 Javadoc 规范,使用/**内容*/格式,不得使用// xxx 方式 需要包含:类的概括描述、类的详细描述、类的作者
/**
* 〈一句话功能简述〉
* 〈功能详细描述〉
* @author 作者
* @see [相关类/方法](可选)
* @since [产品/模块版本] (可选)
*/
【强制】 类文件头注释,文件头注释需要包含:文件创建时间,版权信息、文件名、作者。
/**
* Copyright (C),2002-2018, 苏宁软件技术有限公司
* FileName: 文件名
* Author: 作者
* Date: 2017年12月28日 下午2:16:23
* Description: //模块目的、功能描述
* History: //修改记录
(可选)
*
【强制】 方法注释:包含:方法的功能描述、方法的每一个参数的含义、方法的返回值说明(可选)、以及作者。
/**
*功能描述:
* <详细描述>
* @param 入参 参数说明
* @return 返回参数 参数说明
* @author 作者
* @see [相关类/方法](可选)
* @since [产品/模块版本](可选)
*/
【强制】 修改别人代码时的注释方法要补充,功能添加在方法中注释添加,方法体内在相应代码行处添加行注释,来说明。
【强制】 方法内部单行注释,在被注释语句上方另起一行,使用//注释。方法内部多行注释使用/* */注释,注意与代码对齐。
说明:在逻辑处理中的关键步骤要编写业务注释,便于自己和他人读懂代码处理。
【强制】 成员变量注释。
说明:
常量注释:采用“/** */”注释符,准确表达变量含义即可;
变量注释:采用“//”注释符,特指方法内的局部变量。
System.out.println
打印 log。Log
的 tag
不能是" "。Tag
: 统一使用当前的类名命名private static final String TAG = XXX.class.getSimpleName();
Log.i(TAG,"");
Text
:要说明信息的情况Log.i(TAG,"登录请求=”+” [{"mobile":"15622334614","pwd":"123456"}]");
Log.i(TAG,"登录返回=”+” [{"XXX":"XXX","XXX":"XXX"}]");
log.i
输出;一些警告,异常用log.w
输出等,不得滥用log.w
,log.e
[1] 宋志高. Android 编码规范. 中国, 2017.
[2] Alibaba. 阿里巴巴 Java 开发手册终极版. 电子工业出版社, 中国, 1.3.0 edition, 2017.