先说一个最大也是最奇葩的问题,工程里所有Service接口的实现类里的方法都没有加@Override,if/else/while也不加大括号,经常一堆if/else套在一起看着就难受,80%的代码没有注释
原代码 :
public String getUrl(String key) {
// 设置URL过期时间为10年 3600l* 1000*24*365*10
Date expiration = new Date(new Date().getTime() + 3600l * 1000 * 24 * 365 * 10);
// 生成URL
URL url = ossClient.generatePresignedUrl(bucketName, key, expiration);
if (url != null) {
return url.toString();
}
return null;
}
}
获取当前毫秒数:System.currentTimeMillis(); 而不是new Date().getTime();
public Date() {
this(System.currentTimeMillis());
}
new Date()所做的事情其实就是调用了System.currentTimeMillis()。如果仅仅是需要或者毫秒数,那么完全可以使用System.currentTimeMillis()去代替new Date(),效率上会高一点。况且很多人喜欢在同一个方法里面多次使用new Date(),通常性能就是这样一点一点地消耗掉。
原代码:
public void timer() {
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.HOUR_OF_DAY, 9); // 控制时
calendar.set(Calendar.MINUTE, 0); // 控制分
calendar.set(Calendar.SECOND, 0); // 控制秒
Date time = calendar.getTime(); // 得出执行任务的时间
Timer timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask() {
public void run() {
PersonService personService = (PersonService)ApplicationContext.getBean("personService");
//System.out.println("-------设定要指定任务--------");
}
}, time, 1000*60*60*24);// 这里设定将延时每天固定执行
}
多线程并行处理定时任务时,Timer运行多个TimeTask,只要其中之一没有捕获抛出的异常,其它任务便会自动终止运行,使用ScheduledExecutorService则没有这个问题。
原代码:
/**
* 验证手机号码
* @param mobiles
* @return
*/
public static boolean checkMobileNumber(String mobileNumber){
boolean flag = false;
try{
Pattern regex = Pattern.compile("^(((13[0-9])|(15([0-3]|[5-9]))|(18[0,5-9]))\\d{8})|(0\\d{2}-\\d{8})|(0\\d{3}-\\d{7})$");
Matcher matcher = regex.matcher(mobileNumber);
flag = matcher.matches();
}catch(Exception e){
flag = false;
}
return flag;
}
在使用正则表达式时,利用好其预编译功能,可以有效加快正则匹配速度,不要在方法体内定义:Pattern pattern = Pattern.compile(规则);
可以在类里预先定义,如
private static Pattern NUMBER_PATTERN = Pattern.compile("[0-9]+");
诸多命名问题:
对于Service和DAO类,基于SOA的理念,暴露出来的服务一定是接口,内部的实现类用Impl的后缀与接口区别。
魔法值直接出现在代码中。
除常用方法(如getXxx/isXxx)等外,不要在条件判断中执行复杂的语句,将复杂逻辑判断的结果赋值给一个有意义的布尔变量,以提高可读性。
大量的POJO类没有写toString方法,如果不重写toString,打印其会得到输出:xxxx@xxxxxxx的类名加地址形式,重写toString后,在方法执行抛出异常时,可以直接调用POJO的toString()方法打印其属性值,便于排查问题。使用工具类source> generate toString时,如果继承了另一个POJO类,注意在前面加一下super.toString。
POJO类属性必须使用包装数据类型,数据库的查询结果可能是null,因为自动拆箱,所以用基本数据类型接收有空指针风险。
定义DO/DTO/VO等POJO类时,不要加任何属性默认值。在数据库更新其他字段时,被初始化赋值的字段也会更新。
用到List的属性,在需要使用的时候再new出来。
原代码:
for (Element td : tds) {
switch (j) {
case 0:
score.sch_year = td.text().substring(10, 11);
score.term = td.text().substring(0, 9) + "-0" + score.sch_year;
break;
.......
循环体内,字符串的联接方式,使用StringBuilder的append方法进行扩展。反编译出的字节码文件显示每次循环都会new出一个StringBuilder对象,然后进行append操作,最后通过toString方法返回String对象,造成内存资源浪费。
for (int i = 0; i < verify_code_length; i++) {
code += (int) (Math.random() * 10);
}
Math.random() 这个方法返回是double类型,注意取值的范围[0,1)(能够取到零值,注意除零异常),如果想获取整数类型的随机数,不要将x放大10的若干倍然后取整,直接使用Random对象的nextInt或者nextLong方法。
写一堆set为什么不直接在POJO里写个构造方法?
缺少@Autowired注解
return一个赋值表达式?为什么不直接return调用方法的返回值,而要多此一举。
使用已过时的方法,用Calendar.get(Calendar.MINUTE)和Calendar.get(Calendar.HOUR_OF_DAY)代替.。
捕获异常不进行处理,只需在方法出声明throws。
捕获多个类型的异常,可以直接写成
try {
......
} catch (Exception1 | Exception2 e) {
......
}
还有大量的POJO类里用Map来存放对象,Controller也返回一个超大的Map,而Spring官方推荐的是用ResponseEntity来作为返回对象,ResponseEntity标识整个http相应:状态码、头部信息以及相应体内容,因此可以使用其对http响应实现完整配置。