如何提高Java代码质量-优雅的写代码
写在前面的话:
- 先让代码跑起来再考虑优化,警惕过早优化代码
- 代码review很重要
- 阅读代码的时间比写代码的时间多得多
应该注意的规范
-
所有文件的开头都要有Java文档的注释
-
尽量使类中所有的变量都是私有的,只能通过方法来访问它们
-
常量应该全部大写,单词之间由下划线分隔(例如,MAX_WORK_HOURS)
-
一行应该包含一个语句
-
在使用if-else、for、while、do和switch语句时应该使用大括号
-
避免一行中超过80个字符
-
数组标识:要用"int[] packets",而不是"int packets[]",后一种永远也不要用
-
不要在循环中构造和释放对象
-
在任何可能的地方让类为Final,标记为final的类不能被扩展
-
在任何可能的地方使用局部变量,属于方法调用部分的自变量和声明为此调用一部分的临时变量存储在栈中
-
用代码有效处理内存溢出,OutOfMemoryError是由于内存不够后普遍会遇到的问题
-
尽量使用懒加载,即在需要时才创建
-
try...catch只允许包裹当前会抛出异常的代码块,多余的代码块会影响资源回收。并且 try...catch 禁止在循环体内部使用
-
集合如果能估计到待添加的内容长度,请指定容器的初始长度
比如ArrayList、LinkedLlist、StringBuilder、StringBuffer、HashMap、HashSet -
在java编程过程中,进行数据库连接,I/O流操作,在使用完毕后,及时关闭以释放资源。因为对这些大对象的操作会造成系统大的开销。
-
在java+Oracle的应用系统开发中,java中内嵌的SQL语言应尽量使用大写形式,以减少Oracle解析器的解析负担。
for循环的优化
//replace
for( int i = 0; i < collection.size(); i++) {
...
}
//with...
for( int i = 0, n = collection.size(); i < n; i++) {
...
}
循环尽量不要不断创建对象引用,
//这种做法会导致内存中有count份Object对象引用存在,count很大的话,就耗费内存了
//replace
for (int i = 1; i <= count; i++){
Object obj = new Object();
}
//with...
Object obj =null;
for (int i = 1; i <= count; i++){
obj = new Object();
}
字符串优化
String str1 = "str";
String str2 = "ing";
String str3 = "str" + "ing";//常量池中的对象
String str4 = str1 + str2; //在堆上创建的新的对象
String str5 = "string";//常量池中的对象
System.out.println(str3 == str4);//false
System.out.println(str3 == str5);//true
System.out.println(str4 == str5);//false
//使用append代替+
//replace
String str = "profit = revenue( “ + revenue +
”) - cost( “ + cost + ”)";
//with
String str = new StringBuffer().append( "profit = revenue( “).
append( revenue).append( “) - cost( “).
append( cost).append( “)“).toString();
字符串和字符串常量equals的时候将字符串常量写在前面,能避免NPE
String str = "aac";
//replace
str.equals("aac");
//with
"123".equals(str);
使用常量
-
常量声明为
static final
,并以大写命名在编译期间就可以把这些内容放入常量池中,避免运行期间计算生成常量的值。另外,将常量的名字以大写命名也可以方便区分出常量与变量 -
同类型的多个常量请使用枚举
-
单一常量请使用 interface 声明类包裹, interface 天生就是静态公开的。
Spring 注入
Spring 注入方式注入请使用 Construction 方式进行注入,传统的@Autowired注入方式容易产生 NPE 错误,因此 Spring 强烈建议使用 Construction 代替 Field 注入。如:
class Foo {
//replace
//@Autowired private SomeService someService;
//with
private final SomeService someService;
@Autowired public Foo(SomeService someService) {
this.someService = someService;
}
}
数组复制
尽量使用System.arraycopy ()代替通过来循环复制数组
单元测试
- 单元测试很有必要
- 单元测试应该是自动执行的,并且非交互式的
- 单元测试必须使用assert验证,禁止使用system.out.print 人肉验证
异常
日志
- 使用同一的日志框架处理日志,有利于维护和同一各类日志处理方式
- 日志保存时间应该超过15天,便于发现其他周期性出现的异常
- 日志输出必须是是以条件形式或者占位符形式,并且日志打印方式应该是以当前异常信息和堆栈异常信息,堆栈信息不处理向上抛出
if(logger.isDebugEnabled){
//打印当前异常错误信息+不处理的异常向上抛
logger.debug("log info"+ e.localErrrorMsg,e)
}
- error 级别只记录系统逻辑出错、异常等重要的错误信息,生产不打debug日志选择性打印info
未完待续 - - -
参考链接:
http://www.cnblogs.com/xrq730/p/4865416.html
https://mp.weixin.qq.com/s/SXL83Iq3z1lsVrioMjhkMQ
编程是一门艺术,程序员是艺术家,其他人是码农!!