一、在if/else/for/while/do语句中必须使用大括号,即使只有一行代码,避免使用下面的形式:if (condition) statements
二、所有的覆写方法,必须加@Override注解
三、避免通过一个类的对象引用访问此类的静态变量或静态方法,无谓增加编译器解析成本,直接用类名来访问
四、Object的equals方法容易抛空指针异常,应使用常量或确定有值的对象来调用equals。
五、不能使用过时的类和方法
六、在一个switch块内,每个case要么通过break/return等来终止,要么注释说明程序将继续执行到哪一个case为止;在一个switch块内,都必须包含一个default语句并且放在最后,即使它什么代码也没有。
switch (x) {
case 1:
break;
case 2:
break;
default:
}
七、对于Service和DAO类,基于SOA的理念,暴露出来的服务一定是接口,内部的实现类用Impl的后缀与接口区别
public interface DemoService{
void f();
}
public class DemoServiceImpl implements DemoService {
@Override
public void f(){
System.out.println("hello world");
}
}
八、常量命名应该全部大写,单词间用下划线隔开,力求语义表达完整清楚,不要嫌名字长
九、所有的枚举类型字段必须要有注释,说明每个数据项的用途。
public enum TestEnum {
/**
* agree
*/
agree("agree"),
/**
* reject
*/
reject("reject");
private String action;
TestEnum(String action) {
this.action = action;
}
public String getAction() {
return action;
}
}
十、不允许任何魔法值(即未经定义的常量)直接出现在代码中
十一、中括号是数组类型的一部分
十二、关于基本数据类型与包装数据类型的使用标准如下:
- 所有的POJO类属性必须使用包装数据类型。
- RPC方法的返回值和参数必须使用包装数据类型。
- 所有的局部变量推荐使用基本数据类型。
说明:POJO类属性没有初值是提醒使用者在需要使用时,必须自己显式地进行赋值,任何NPE问题,或者入库检查,都由使用者来保证
十三、单个方法的总行数不超过80行。 说明:除注释之外的方法签名、结束右大括号、方法内代码、空行、回车及任何不可见字符的
十四、所有的抽象方法(包括接口中的方法)必须要用javadoc注释、除了返回值、参数、异常说明外,还必须指出该方法做什么事情,实现什么功能。 说明:如有实现和调用注意事项,请一并说明
十五、集合初始化时,指定集合初始值大小。 说明:HashMap使用如下构造方法进行初始化,如果暂时无法确定集合大小,那么指定默认值(16)即可。
Negative example:
Map<String, String> map = new HashMap<String, String>();
Positive example:
Map<String, String> map = new HashMap<String, String>(16);
十六、long或者Long初始赋值时,必须使用大写的L,不能是小写的l,小写容易跟数字1混淆,造成误解
Negative example:
//It is hard to tell whether it is number 11 or Long 1.
Long warn = 1l;
Positive example:
Long notwarn = 1L;
十七、所有的包装类对象之间值的比较,全部使用equals方法比较
十八、获取当前毫秒数:System.currentTimeMillis(); 而不是new Date().getTime()
十九、Apache BeanUtils性能较差,可以使用其他方案比如Spring BeanUtils, Cglib BeanCopier
二十、异常类命名使用Exception结尾
二十一、必须回收自定义的ThreadLocal变量,尤其在线程池场景下,线程经常会被复用,如果不清理自定义的 ThreadLocal变量,可能会影响后续业务逻辑和造成内存泄露等问题。尽量在代理中使用try-finally块进行回收
二十二、所有编程相关的命名均不能以下划线或美元符号开始
二十三、抽象类命名使用Abstract或Base开头
二十四、线程资源必须通过线程池提供,不允许在应用中自行显式创建线程。
说明:使用线程池的好处是减少在创建和销毁线程上所花的时间以及系统资源的开销,解决资源不足的问题。如果不使用线程池,有可能造成系统创建大量同类线程而导致消耗完内存或者“过度切换”的问题
二十五、事务场景中,抛出异常被catch后,如果需要回滚,一定要手动回滚事务。
@Service
public class UserServiceImpl implements UserService {
@Autowired
private DataSourceTransactionManager transactionManager;
@Override
@Transactional
public void save(User user) {
DefaultTransactionDefinition def = new DefaultTransactionDefinition();
// explicitly setting the transaction name is something that can only be done programmatically
def.setName("SomeTxName");
def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
TransactionStatus status = transactionManager.getTransaction(def);
try {
// execute your business logic here
//db operation
} catch (Exception ex) {
transactionManager.rollback(status);
throw ex;
}
}
}
二十六、包名统一使用小写,点分隔符之间有且仅有一个自然语义的英语单词。包名统一使用单数形式,但是类名如果有复数含义,类名可以使用复数形式
二十七、定义DO/DTO/VO等POJO类时,不要加任何属性默认值
二十八、循环体内,字符串的联接方式,使用StringBuilder的append方法进行扩展。
说明:反编译出的字节码文件显示每次循环都会new出一个StringBuilder对象,然后进行append操作,最后通过toString方法返回String对象,造成内存资源浪费
二十九、避免采用取反逻辑运算符。
说明: 取反逻辑不利于快速理解,并且取反逻辑写法必然存在对应的正向逻辑写法
三十、除常用方法(如getXxx/isXxx)等外,不要在条件判断中执行复杂的语句,将复杂逻辑判断的结果赋值给一个有意义的布尔变量,以提高可读性。
说明:很多if语句内的逻辑相当复杂,阅读者需要分析条件表达式的最终结果,才能明确什么样的条件执行什么样的语句,那么,如果阅读者分析逻辑表达式错误呢?
Negative example:
if ((file.open(fileName, "w") != null) && (...) || (...)) {
// ...
}
Positive example:
boolean existed = (file.open(fileName, "w") != null) && (...) || (...);
if (existed) {
//...
}
三十、禁止使用构造方法BigDecimal(double)的方式把double值转化为BigDecimal对象
说明:反编译出的字节码文件显示每次循环都会new出一个StringBuilder对象,然后进行append操作,最后通过toString方法返回String对象,造成内存资源浪费。
Negative example:
BigDecimal good1 = new BigDecimal(0.1);
Positive example:
BigDecimal good1 = new BigDecimal("0.1");
BigDecimal good2 = BigDecimal.valueOf(0.1);
----------------- 文章如有问题,请下方回复指出,感谢查阅😁 -----------------