Java:IOException的危险自返回递归函数?

时间:2010-04-12 16:00:26

标签: java error-handling recursion

我使用if子句进行了非常错误的异常处理。如果找不到路径,则会发生异常。异常再次返回该函数。该函数是递归的。安全

$ javac SubDirs.java 
$ java SubDirs
Give me an path.
.
Dir1
Dir2
Give me an path.
IT WON'T FIND ME, SO IT RETURNS ITSELF due to Exception caught
Give me an path.

Subdirs.java的代码如下所示:

import java.io.*;
import java.util.*;

public class SubDirs {
    private List<File> getSubdirs(File file) throws IOException {
        List<File> subdirs = Arrays.asList(file.listFiles(new FileFilter() {
                    public boolean accept(File f) {
                    return f.isDirectory();
                    }
                    }));
        subdirs = new ArrayList<File>(subdirs);

        List<File> deepSubdirs = new ArrayList<File>();
        for(File subdir : subdirs) {
            deepSubdirs.addAll(getSubdirs(subdir)); 
        }
        subdirs.addAll(deepSubdirs);
        return subdirs;
    }

    public static void search() {
        try{
            BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
            String s;
            System.out.println("Give me an path.");
            while ((s = in.readLine()) != null && s.length() != 0){
                SubDirs dirs = new SubDirs();
                List<File> subDirs = dirs.getSubdirs(new File(s));
                for ( File f : subDirs ) {
                    System.out.println(f.getName());
                }
                System.out.println("Give me an path.");
            }
        }catch(Exception e){
                    // Simple but is it safe?
            search();
        }
    }

    public static void main(String[] args) throws IOException {
        search();
    }
}

3 个答案:

答案 0 :(得分:2)

是的,在你输入数千次错误路径之前是安全的。

答案 1 :(得分:1)

有争议的。我认为这会留下一堆无用的堆栈帧 - 除非您尝试在移动设备上重用此代码,否则可能不是问题。 无论如何,如果没有更好的说法,我就不会让它通过代码审查。

为了更好的可理解性和可维护性,养成编码你的意思的习惯:如果你想让代码循环以重试错误,那么编写一个循环。递归感觉更顺畅,但是,由于它不是异常处理程序中的常见做法,因此增加了意外因素。如果我是这个代码的未来维护者,我想知道递归是故意还是错误 - 请给我一个评论来解释递归是故意的。

我现在很乐意更换几行普通代码,以便更好地维护,以便以后更轻松地进行故障排除。

public static void search() {

  boolean succeeded = false;
  int attemptsLeft = MAX_ATTEMPTS;
  while (! succeeded && (--attemptsLeft > 0)) {

    try{
        BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
        String s;
        System.out.println("Give me an path.");
        while ((s = in.readLine()) != null && s.length() != 0){
            SubDirs dirs = new SubDirs();
            List<File> subDirs = dirs.getSubdirs(new File(s));
            for ( File f : subDirs ) {
                System.out.println(f.getName());
            }
            System.out.println("Give me an path.");
        }

        succeeded = true;

    }catch(Exception e){
        // ALWAYS LEAVE YOURSELF A CLUE TO WHAT HAPPENED
        // e.g. the exception caught may not be the exception you expected
        e.printStackTrace();
    }

  } // while not succeeded yet

  if (! succeeded) {
    log("Hmm ... bailing search() without succeeding");
  }
}

答案 2 :(得分:0)

每次search()失败时,都会在调用堆栈上创建另一个search()实例。在这种情况下,它会提示用户输入,我想用户很可能会在堆栈溢出之前放弃,所以我想这里的危险很小。但是如果你有一个应用程序重新尝试失败或转移到可能很长的列表中的下一个项目,你可以用这种方法溢出堆栈。

我建议更好的方法是将try / catch块放在while循环中,并在失败时再次循环,而不是进行递归调用。类似于 - 警告 - 未经测试的建议代码:

public static void search() { 
    BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); 
    String s; 
    System.out.println("Give me an path."); 
    while ((s = in.readLine()) != null && s.length() != 0){ 
        try
        { 
            SubDirs dirs = new SubDirs(); 
            List<File> subDirs = dirs.getSubdirs(new File(s)); 
            for ( File f : subDirs ) { 
                System.out.println(f.getName()); 
            }
        }
        catch (Exception e) {
            System.out.println("Something went wrong! Everybody scream and run in circles!");
        }
    System.out.println("Give me an path."); 
    } 
}