Java-编程优化

不使用 !=null

一些实践建议:

  1. 返回类型是collections,返回结果为空时,可以返回一个空的collections(empty list)而不是返回null,这样就可以大胆地处理这个返回。(忽略判空)

  2. 返回类型不是collections,那么就返回个空对象(而非null对象),举例:

    1
    2
    3
    4
    5
    6
    public interface Action{
    void doSomething();
    }
    public interface Parser{
    Action findAction(String userInput);
    }

    这个例子里调用 Parser#findAction会有空指针问题。改造下(使用Null Object pattern(空对象模式)):

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    public class  MyParser implements Parser{
    private static Action DO_NOTHING = new Action(){
    public void doSomething(){
    /* do nothing */
    }
    };
    public Action findAction(String userInput){
    //...
    if(/* we can't find any actions */){
    return DO_NOTHING;
    }
    }
    }

    对比这俩例子的调用

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    //冗余:每获取一个对象,就判一次空
    Parser parser = ParserFactory.getParser();
    if (parser == null) {
    // now what?
    // this would be an example of where null isn't (or shouldn't be) a valid response
    }
    Action action = parser.findAction(someInput);
    if (action == null) {
    // do nothing
    } else {
    action.doSomething();
    }
    1
    2
    //精简
    ParserFactory.getParser().findAction(someInput).doSomething();

其他回答精选

  1. 如果要用equal方法,请用object<不可能为空>.equal(object<可能为空>))
    例如:
    1
    2
    3
    "bar".equals(foo)
    //而不是
    foo.equals("bar")
  2. Java8或者guava lib中,提供了Optional类,这是一个元素容器,通过它来封装对象,可以减少判空。不过代码量还是不少。不爽。
  3. 如果你想返回null,请停下来想一想,这个地方是否更应该抛出一个异常

代码优化技巧

循环嵌套-外小内大

1
2
3
4
5
6
7
8
stratTime = System.nanoTime();
for (int i = 0; i < 10000000; i++) {
for (int j = 0; j < 10; j++) {

}
}
endTime = System.nanoTime();
System.out.println("外大内小耗时:"+ (endTime - stratTime));

应改为

1
2
3
4
5
6
7
8
stratTime = System.nanoTime();
for (int i = 0; i <10 ; i++) {
for (int j = 0; j < 10000000; j++) {

}
}
endTime = System.nanoTime();
System.out.println("外小内大耗时:"+(endTime - stratTime));

前者耗时:200192114
后者耗时:97995997

提取与循环无关的表达式-放循环外

1
2
3
4
5
6
fstratTime = System.nanoTime();
for (int i = 0; i < 10000000; i++) {
i=i*a*b;
}
endTime = System.nanoTime();
System.out.println("未提取耗时:"+(endTime - stratTime));

应改为

1
2
3
4
5
6
7
stratTime = System.nanoTime();
int size = list.size();
for (int i = 0; i < size; i++) {

}
endTime = System.nanoTime();
System.out.println("优化list耗时:"+(endTime - stratTime));

前者耗时:27375
后者耗时:2444 (list.size()每次循环都会被执行一次)

异常捕获-放循环外

1
2
3
4
5
6
7
8
stratTime = System.nanoTime();
for (int i = 0; i < 10000000; i++) {
try {
} catch (Exception e) {
}
}
endTime = System.nanoTime();
System.out.println("在内部捕获异常耗时:"+(endTime - stratTime));

应改为

1
2
3
4
5
6
7
8
9
stratTime = System.nanoTime();
try {
for (int i = 0; i < 10000000; i++) {
}//加入Java开发交流君样:756584822一起吹水聊天
} catch (Exception e) {

}
endTime = System.nanoTime();
System.out.println("在外部捕获异常耗时:"+(endTime - stratTime));

前者耗时:12150142
后者耗时:1955 (捕获异常非常耗时)