虽然手册上说的一些不是强制的,但是,我还是希望自己能强制执行这些,规范是养成的,需要时间的积累,需要代码的累积.一段代码可以看出一个人的修养.以下的示例,我只会举一些正例,因为我们需要忘记反例,而不是避免这些.–>Newt
参考至阿里巴巴Java开发手册:遵从码出高效, 码出质量的原则,我写出这样一篇完整的开发规范.所谓无规矩不成方圆,无规范不能协作.代码的字里行间流淌的是软件生命中的血液, 质量的提升是尽可能少踩坑,杜绝踩重复的坑,切实提升质量意识
代码中的命名严禁使用拼音与英文混合的方式,更不允许直接使用中文的方式.
正例: alibaba / taobao / youku / hangzhou 等国际通用的名称, 可视同英文.
类名使用 UpperCamelCase 风格,必须遵从驼峰形式,但以下情形例外: DO / BO / DTO / VO / AO
正例: MarcoPolo / UserDO / XmlService / TcpUdpDeal / TaPromotion
方法名、参数名、成员变量、局部变量都统一使用 lowerCamelCase 风格,必须遵从驼峰形式.
正例: localValue / getHttpMessage() / inputUserId
常量命名全部大写,单词间用下划线隔开,力求语义表达完整清楚,不要嫌名字长.
正例: MAX_STOCK_COUNT
中括号是数组类型的一部分,数组要规范
正例: String[] args;
包名统一使用小写,点分隔符之间有且仅有一个自然语义的英语单词.包名统一使用单数形式,但是类名如果有复数含义,类名可以使用复数形式.
正例: 应用工具类包名为 com.alibaba.open.util、类名为 MessageUtils(此规则参考spring 的框架结构)
为了达到代码自解释的目标,任何自定义编程元素在命名时,使用尽量完整的单词组合来表达其意.
正例: 从远程仓库拉取代码的类命名为 PullCodeFromRemoteRepository。
如果模块、 接口、类、方法使用了设计模式,在命名时体现出具体模式.
正例: public class OrderFactory;
正例: 接口方法签名: void f();
接口和实现类的命名有两套规则:
对于 Service 和 DAO 类,基于 SOA 的理念,暴露出来的服务一定是接口,内部的实现类用 Impl 的后缀与接口区别.
正例: CacheServiceImpl 实现 CacheService 接口。
如果是形容能力的接口名称,取对应的形容词做接口名(通常是–able 的形式)。
正例: AbstractTranslator 实现 Translatable。
枚举类名建议带上 Enum 后缀,枚举成员名称需要全大写,单词间用下划线隔开。
枚举其实就是特殊的常量类,且构造方法被默认强制是私有。
正例: 枚举名字为 ProcessStatusEnum 的成员名称: SUCCESS / UNKOWN_REASON。
各层命名规约:
ervice/DAO 层方法命名规约
领域模型命名规约
Long a = 2l; 写的是数字的 21,还是 Long 型的 2?
不要使用一个常量类维护所有常量, 按常量功能进行归类,分开维护.
大而全的常量类,非得使用查找功能才能定位到修改的常量,不利于理解和维护
正例: 缓存相关常量放在类 CacheConsts 下; 系统配置相关常量放在类 ConfigConsts 下。
如果变量值仅在一个范围内变化,且带有名称之外的延伸属性, 定义为枚举类。下面正例中的数字就是延伸信息,表示星期几。
正例: public Enum { MONDAY(1), TUESDAY(2), WEDNESDAY(3), THURSDAY(4), FRIDAY(5), SATURDAY(6),SUNDAY(7);}
说明: 运算符包括赋值运算符=、逻辑运算符&&、加减乘除符号等。
如果使用 tab 缩进,必须设置 1 个 tab 为 4 个空格。 IDEA 设置 tab 为 4 个空格时,请勿勾选 Use tab character;而在 eclipse 中,必须勾选 insert spaces for tabs。
正例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20public 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");
// 在右大括号后直接结束,则必须换行
}
}
注释的双斜线与注释内容之间有且仅有一个空格。
正例: // 注释内容, 注意在//和注释内容之间有一个空格
正例:
1
2
3
4
5
6
StringBuffer sb = new StringBuffer();
// 超过 120 个字符的情况下,换行缩进 4 个空格, 点号和方法名称一起换行
sb.append("zi").append("xin")...
.append("huang")...
.append("huang")...
.append("huang");
方法参数在定义和传入时,多个参数逗号后边必须加空格
正例: 下例中实参的"a",后边必须要有一个空格。
method("a", "b", "c");
正例:
1
2
3
4int a = 3;
long b = 4L;
float c = 5F;
StringBuffer sb = new StringBuffer();
没有必要插入多个空行进行隔开。
说明: getObject()与 get0bject()的问题。一个是字母的 O,一个是数字的 0,加@Override可以准确判断是否覆盖成功。另外,如果在抽象类中对方法签名进行修改,其实现类会马上编译报错。
相同参数类型,相同业务含义,才可以使用 Java 的可变参数,避免使用 Object。
说明: 可变参数必须放置在参数列表的最后。
正例: public User getUsers(String type, Integer... ids) {...}
说明: java.net.URLDecoder 中的方法 decode(String encodeStr) 这个方法已经过时,应该使用双参数 decode(String source, String encode)。接口提供方既然明确是过时接口,那么有义务同时提供新的接口; 作为调用方来说,有义务去考证过时方法的新实现是什么。
Object 的 equals 方法容易抛空指针异常,应使用常量或确定有值的对象来调用equals
正例: "test".equals(object);
说明: 对于 Integer var = ? 在-128 至 127 范围内的赋值, Integer 对象是在IntegerCache.cache 产生,会复用已有对象,这个区间内的 Integer 值可以直接使用==进行判断,但是这个区间之外的所有数据,都会在堆上产生,并不会复用已有对象,这是一个大坑,推荐使用 equals 方法进行判断
关于基本数据类型与包装数据类型的使用标准.
说明: POJO 类属性没有初值是提醒使用者在需要使用时,必须自己显式地进行赋值,任何NPE 问题,或者入库检查,都由使用者来保证。
- 所有的 POJO 类属性必须使用包装数据类型。
- RPC 方法的返回值和参数必须使用包装数据类型。
- 所有的局部变量使用基本数据类型。
正例: 数据库的查询结果可能是 null,因为自动拆箱,用基本数据类型接收有 NPE 风险。
说明: 注意 serialVersionUID 不一致会抛出序列化运行时异常。
说明: 在方法执行抛出异常时,可以直接调用 POJO 的 toString()方法打印其属性值,便于排查问题。
说明:
1
2
3
4
String str = "a,b,c,,";
String[] ary = str.split(",");
// 预期大于 3,结果是 3
System.out.println(ary.length);
反编译出的字节码文件显示每次循环都会 new 出一个 StringBuilder 对象,然后进行append 操作,最后通过 toString 方法返回 String 对象,造成内存资源浪费。
说明: 对象的 clone 方法默认是浅拷贝,若想实现深拷贝需要重写 clone 方法实现属性对象的拷贝。
今天依旧晴空,空气清晰,吃了一根梦龙,哇,感觉贼爽!!