編程點滴-關于boolean常量在判斷中的位置
今天review某同學的代碼時發現這樣一個情況:
DEBUG是一個boolean的常量,原來是
if(DEBUG){
doSomething();
}
后來因為要求在安全模式下不準打印log,于是改成這樣:
if((!isSecMode()) && DEBUG){
doSomething();
}
現在又增加了一種新的模式警用模式,于是改成這樣:
if((!isSecMode()) && (!isPoliceMode()) && DEBUG){
doSomething();
}
這樣會造成一點性能和空間損失的。
如果編譯器發現if(false)或者if(false && ...)這樣的語句,直接就不會編譯進字節碼中,這是由短路規則所決定的。
而如果把DEBUG放在最后,由于不符合短路規則,后面的語句也是沒必要編譯進來的,但是要保證前面的判斷是要執行的。
于是就生成了這樣一句話
if ((!ts.isSecMode()) && (!ts.isPoliceMode()));
白白要做兩次判斷!
下面看看完整的代碼。
源代碼:
public class TestSeven {
public void doSomething(){
}
public boolean isSecMode(){
doSomething();
return false;
}
public boolean isPoliceMode(){
doSomething();
return false;
}
private static final boolean DEBUG = false;
public static void main(String[] args){
TestSeven ts = new TestSeven();
if(DEBUG && !ts.isSecMode() && !ts.isPoliceMode()){
System.out.println("DEBUG1");
}
if(!ts.isSecMode() && !ts.isPoliceMode() && DEBUG){
System.out.println("DEBUG2");
}
}
}
反編譯之后是這樣的:
public class TestSeven
{
private static final boolean DEBUG = false;
public void doSomething()
{
}
public boolean isSecMode()
{
doSomething();
return false;
}
public boolean isPoliceMode() {
doSomething();
return false;
}
public static void main(String[] args)
{
TestSeven ts = new TestSeven();
if ((!ts.isSecMode()) && (!ts.isPoliceMode()));
}
}
從反編譯的代碼中可以看到,不管是System.out.println("DEBUG1");還是System.out.println("DEBUG2");皆是虛妄,根本就直接被編譯器過濾掉了。
但是有短路規則的if(DEBUG && !ts.isSecMode() && !ts.isPoliceMode()),連一點痕跡都沒留下來,而沒有短路規則的第二條判斷,就不得不留下if ((!ts.isSecMode()) && (!ts.isPoliceMode()));