Java开发手册及规范

前言
为了利于项目维护以及规范开发,促进成员之间Code Review的效率,故提出以下开发规范
根据约束力强弱, 规约依次分为强制、推荐、参考三大类:

【强制】必须遵守,违反本约定或将会引起严重的后果;

【推荐】尽量遵守,长期遵守有助于系统稳定性和合作效率的提升;

【参考】充分理解,技术意识的引导,是个人学习、团队沟通、项目合作的方向。

一、命名规范
1.【强制】代码中的命名均不能以下划线或美元符号开始,也不能以下划线或美元符号结束。

// 错误示例: 
name / name / $name / name / name$ / name

2.【强制】代码中的命名严禁使用拼音与英文混合的方式,更不允许直接使用中文的方式(即使纯拼音命名方式也要避免采用)。

// 正确示例:
alibaba / taobao / youku / hangzhou 等国际通用的名称,可视同英文。

// 错误示例:
DaZhePromotion
getPingfenByName()
int 某变量 = 3

3.【强制】类名使用UpperCamelCase风格。

// 正确示例:
MarcoPolo / UserDO / XmlService

// 错误示例:
macroPolo / UserDo / XMLService

4.【强制】方法名、参数名、成员变量、局部变量都统一使用lowerCamelCase风格,必须遵从驼峰形式。

// 正确示例:
localValue / getHttpMessage() / inputUserId

5.【强制】常量命名全部大写,单词间用下划线隔开,力求语义表达完整清楚,不要嫌名字长。

// 正确示例:
MAX_STOCK_COUNT

// 错误示例:
MAX_COUNT

6.【强制】类型与中括号紧挨相连来定义数组。

// 正确示例: 
int[] arrayDemo

// 错误示例: 
String args[]

7.【推荐】为了达到代码自解释的目标,任何自定义编程元素在命名时,使用尽量完整的单词组合来表达其意。杜绝完全不规范的缩写。

//正确示例: 
类命名为PullCodeFromRemoteRepository

// 错误示例:
变量: int a;
AbstractClass“缩写”命名成AbsClass;

8.【参考】枚举类名建议带上Enum后缀,枚举成员名称需要全大写,单词间用下划线隔开。

// 正确示例:
// 枚举类型: 
ProcessStatusEnum
// 成员: 
SUCCESS / UNKNOWN_REASON

二、常量定义
1.【强制】不允许任何魔法值(即未经预先定义的常量)直接出现在代码中。

// 错误示例: 
String key = "Id#taobao_" + x;

2.【强制】long或者Long初始赋值时,使用大写的L,不能是小写的l,小写容易跟数字1混淆,造成误解。

// 正确示例:
Long a = 2L;

// 错误示例:
Long a = 2l;

3.【推荐】如果变量值仅在一个固定范围内变化用enum类型来定义。

三、代码格式
1.【强制】如果是大括号内为空,则简洁地写成{}即可,大括号中间无需换行和空格;如果是非空代码块则:左大括号前不换行;左大括号后换行;右大括号前换行;右大括号后还有 else 等代码则不换行;表示终止的右大括号后必须换行。

2.【强制】左小括号和右边相邻字符之间不出现空格;右小括号和左边相邻字符之间也不出现空格;而左大括号前需要加空格。

3.【强制】if/for/while/switch/do 等保留字与括号之间都必须加空格。

// 正确示例:
if (a == b) {
	method(args1, args2, args3);
} else if (a > b) {
	method(args1, args2, args3);
} else {}

4.【强制】任何二目、三目运算符的左右两边都需要加一个空格。

// 正确示例: 
int y = 0;
int b = 1;
int x = (y > b) ? b : y;

5.【强制】注释的双斜线与注释内容之间有且仅有一个空格。

// 正确示例:
// 这是示例注释,请注意在双斜线之后有一个空格

6.【强制】在进行类型强制转换时,右括号与强制转换值之间不需要任何空格隔开。

// 正确示例:
double first = 3.2d;
int second = (int)first + 2;

7.【强制】方法参数在定义和传入时,多个参数逗号后面必须加空格。

// 正确示例:
method(args1, args2, args3);

8.【推荐】不同逻辑、不同语义、不同业务的代码之间插入一个空行分隔开来以提升可读性。

四、集合处理
1.【强制】判断所有集合内部的元素是否为空,使用 isEmpty()方法,而不是 size()==0 的方式。

// 正确示例:
Map<String, Object> map = new HashMap<>(16);
if(map.isEmpty()) {
	System.out.println("no element in this map.");
}

2.【强制】ArrayList 的 subList 结果不可强转成 ArrayList,否则会抛出 ClassCastException 异常。

3.【强制】使用 Map 的方法 keySet()/values()/entrySet()返回集合对象时,不可以对其进行添加元素操作,否则会抛出 UnsupportedOperationException 异常。

4.【强制】Collections 类返回的对象,如:emptyList()/singletonList()等都是 immutable list,不可对其进行添加或者删除元素的操作。

5.【强制】使用集合转数组的方法,必须使用集合的 toArray(T[] array),传入的是类型完全一致、长度为 0 的空数组。

// 正确示例:
List<String> list = new ArrayList<>(2);
list.add("guan");
list.add("bao");
String[] array = list.toArray(new String[0]);

6.【强制】在无泛型限制定义的集合赋值给泛型限制的集合时,在使用集合元素时,需要进行instanceof 判断,避免抛出 ClassCastException 异常。

// 正确示例:
List<String> generics = null;
List notGenerics = new ArrayList(10);
notGenerics.add(new Object());
notGenerics.add(new Integer(1));
generics = notGenerics;

// 错误示例:
String string = generics.get(0);

7.【强制】不要在 foreach 循环里进行元素的 remove/add 操作。remove 元素请使用 Iterator方式,如果并发操作,需要对 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 (删除元素的条件) {
		iterator.remove();
	}
}

// 错误示例:
for (String item : list) {
	if ("1".equals(item)) {
		list.remove(item);
	} 
}

8.【推荐】集合初始化时,指定集合初始值大小。

9.【推荐】使用 entrySet 遍历 Map 类集合 KV,而不是 keySet 方式进行遍历。

10.【参考】利用 Set 元素唯一的特性,可以快速对一个集合进行去重操作,避免使用 List 的contains()进行遍历去重或者判断包含操作。

五、并发处理
1.【强制】创建线程或线程池时请指定有意义的线程名称,方便出错时回溯。

2.【强制】线程资源必须通过线程池提供,不允许在应用中自行显式创建线程。

3.【强制】线程池不允许使用 Executors 去创建,而是通过 ThreadPoolExecutor 的方式,这样的处理方式让写的同学更加明确线程池的运行规则,规避资源耗尽的风险。

4.【强制】SimpleDateFormat 是线程不安全的类,一般不要定义为 static 变量,如果定义为 static,必须加锁,或者使用 DateUtils 工具类。

正确示例:
private static final ThreadLocal<DateFormat> df = new ThreadLocal<DateFormat>() {
	@Override
	protected DateFormat initialValue() {
		return new SimpleDateFormat("yyyy-MM-dd");
	}
}

5.【强制】高并发时,同步调用应该去考量锁的性能损耗。能用无锁数据结构,就不要用锁;能锁区块,就不要锁整个方法体;能用对象锁,就不要用类锁。

6.【强制】在使用尝试机制来获取锁的方式中,进入业务代码块之前,必须先判断当前线程是否持有锁。锁的释放规则与锁的阻塞等待方式相同。

// 正确示例:
Lock lock = new XxxLock();
boolean isLocked = lock.tryLock();
if (isLocked) {
	try {
		doSomething();
		doOthers();
	} finally {
	lock.unlock();
	}
}

7.【强制】多线程并行处理定时任务时,Timer 运行多个 TimeTask 时,只要其中之一没有捕获抛出的异常,其它任务便会自动终止运行,使用 ScheduledExecutorService 则没有这个问题。

六、控制语句
1.【强制】在一个 switch 块内,每个 case 要么通过 continue/break/return 等来终止,要么注释说明程序将继续执行到哪一个 case 为止;在一个 switch 块内,都必须包含一个 default语句并且放在最后,即使它什么代码也没有。

2.【强制】当 switch 括号内的变量类型为 String 并且此变量为外部参数时,必须先进行 null判断。

// 错误示例:
public class SwitchString {
	public static void main(String[] args) {
		method(null);
  	}

	public static void method(String param) {
		switch (param) {
			// 肯定不是进入这里
			case "sth":
				System.out.println("it's sth");
				break;
			// 也不是进入这里
			case "null":
				System.out.println("it's null");
				break;
			// 也不是进入这里
			default:
				System.out.println("default");
		}
	}
}

3.【强制】在 if/else/for/while/do 语句中必须使用大括号。即使只有一行代码,也禁止不采用大括号的编码方式:if (condition) statements。

4.【强制】三目运算符 condition? 表达式 1 : 表达式 2 中,高度注意表达式 1 和 2 在类型对齐时,可能抛出因自动拆箱导致的 NPE 异常。

// 错误示例:
Integer a = 1;
Integer b = 2;
Integer c = null;
Boolean flag = false;
// a*b 的结果是 int 类型,那么 c 会强制拆箱成 int 类型,抛出 NPE 异常
Integer result=(flag ? a*b : c); 

5.【推荐】表达异常的分支时,少用 if-else 方式,如果非使用 if()…else if()…else…方式表达逻辑,避免后续代码维护困难,请勿超过 3 层。

// 正确示例:
public void findBoyfriend (Man man) {
	if (man.isUgly()) {
		System.out.println("本姑娘是外貌协会的资深会员");
		return;
	}
	if (man.isPoor()) {
		System.out.println("贫贱夫妻百事哀");
		return;
	}
	if (man.isBadTemper()) {
		System.out.println("银河有多远,你就给我滚多远");
		return;
	}
	System.out.println("可以先交往一段时间看看");
}

6.【推荐】除常用方法(如 getXxx/isXxx)等外,不要在条件判断中执行其它复杂的语句,将复杂逻辑判断的结果赋值给一个有意义的布尔变量名,以提高可读性。

7.【推荐】不要在其它表达式(尤其是条件表达式)中,插入赋值语句。

8.【推荐】避免采用取反逻辑运算符。

七、注释
1.【强制】类、类属性、类方法的注释必须使用 Javadoc 规范,使用/*内容/格式,不得使用// xxx 方式。

2.【强制】所有的抽象方法(包括接口中的方法)必须要用 Javadoc 注释、除了返回值、参数、异常说明外,还必须指出该方法做什么事情,实现什么功能。

3.【强制】所有的类都必须添加创建者和创建日期。

4.【强制】方法内部单行注释,在被注释语句上方另起一行,使用//注释。方法内部多行注释使用/* */注释,注意与代码对齐。

5.【强制】所有的枚举类型字段必须要有注释,说明每个数据项的用途。

6.【推荐】代码修改的同时,注释也要进行相应的修改,尤其是参数、返回值、异常、核心逻辑等的修改。

7.【推荐】在类中删除未使用的任何字段、方法、内部类;在方法中删除未使用的任何参数声明与内部变量。

参考文档(阿里java开发手册):Java开发手册(嵩山版).pdf

开源项目路径:https://github.com/alibaba/p3c

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值