2011-05-06 63 views
2

我正在寫一個文件讀取器,返回一個對象,我希望它警告解析錯誤並繼續下一個記錄。錯誤處理中的遞歸?

下面的代碼是這個的明顯實現,但涉及從catch塊內部遞歸。有沒有技術或文體原因不這樣做?

public RecordType nextRecord() throws IOException{ 
    if (reader == null){ 
     throw new IllegalStateException("Reader closed."); 
    } 
    String line = reader.readLine(); 
    if (line == null){ 
     return null; 
    }else{ 
     try { 
      return parseRecord(line); 
     }catch (ParseException pex){ 
      logger.warn("Record ignored due to parse error: " 
       + pex.getMessage()); 
      //Note the recursion here 
      return nextRecord(); 
     } 
    } 
} 
+1

問題在於你的程序會在每個錯誤的記錄中累積堆棧空間,這使得它很容易受到攻擊。例如,當這段代碼成爲Web服務的一部分時,攻擊者只能提供許多錯誤記錄,直到整個服務從堆棧溢出中死亡。這將是一次成功的拒絕服務攻擊。 – Ingo 2011-05-06 12:46:55

+0

@Ingo謝謝,這應該是一個答案:-)。 – 2011-05-06 12:47:43

回答

3

我寧願使用循環。隨着遞歸,你永遠不知道你可以安全地走多深。

String line; 
while((line = reader.readLine()) != null) { 
    try { 
     return parseRecord(line); 
    }catch (ParseException pex){ 
     logger.warn("Record ignored due to parse error: " + pex); 
    } 
} 
return null; 
+0

是的,調試StackOverflowError會是一件痛苦的事情嗎? – 2011-05-06 12:46:07

+0

至少在錯誤出現之前您會看到很多警告。 ;) – 2011-05-06 12:50:25

0

爲什麼不使用循環替代遞歸:

public RecordType nextRecord() throws IOException { 
    if (reader == null) { 
     throw new IllegalStateException("Reader closed."); 
    } 
    for (;;) { 
     String line = reader.readLine(); 
     if (line == null) { 
      return null; 
     } else { 
      try { 
       return parseRecord(line); 
      } catch (ParseException pex) { 
       logger.warn("Record ignored due to parse error: " 
         + pex.getMessage()); 
       // continue to the next record 
      } 
     } 
    } 
} 

風格上,我覺得這是最好。

+0

它稍微不太清楚(有爭議),並且您沒有回答這個問題:是否有任何理由*不使用遞歸。 – 2011-05-06 12:43:33

+0

@C。 Ross:最後一句話是我爲什麼認爲這是可取的,我的(主觀的)論點。 – NPE 2011-05-06 12:44:40

0

讓ParseException傳播回調用方會更簡潔嗎?呼叫者可以決定如何處理。

0

在我看來,無論是調用你的方法,都會一直調用它,直到方法返回null。

我可能會按照以前的海報建議,並使用循環,但我會看看什麼是調用方法(因爲它可能已經使用循環),讓它通過尋找一個異常被拋出。