2010-04-12 5 views
1

J'ai eu des erreurs très gérées avec des clauses if. Une exception se produit si le chemin n'est pas trouvé. Une exception renvoie la fonction à nouveau. La fonction est récursive. Sûr?Java: fonction dangereuse autorégressive-récursive par IOException?

 
$ 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. 

Le code de Subdirs.java ressemble à ceci:

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(); 
    } 
} 
+2

Pourriez-vous nous aider à reformuler votre question? J'ai du mal à comprendre ce que vous demandez. –

+0

@Sauer: Soit A une fonction récursive. Par le def, B est récursif parce qu'il renvoie A. Est-il sûr d'avoir une fonction récursive avec une fonction récursive interne en utilisant try-catch-loop? – hhh

+0

B retourne lui-même. A retourne lui-même. B a A comme structure interne. A est getSubDirs et B est la recherche. – hhh

Répondre

1

Discutable. Je pense que cela laisse un tas de cadres de pile inutiles - peut-être pas une préoccupation, sauf si vous essayez de réutiliser ce code sur un appareil mobile. Peu importe, je ne le laisserais pas passer un examen de code sans plus convaincant qu'il n'y a pas de meilleure façon.

Pour une meilleure compréhensibilité et la maintenabilité, prenez l'habitude de coder ce que vous entendez: si vous avez l'intention le code à boucle pour une nouvelle tentative sur erreur, code, puis une boucle. La récursion est plus légère, mais, comme ce n'est pas une pratique courante chez les gestionnaires d'exceptions, elle augmente le facteur de surprise. si j'étais un futur mainteneur de ce code, je me demanderais si la récursion est intentionnelle ou un bug - s'il vous plaît laissez-moi un commentaire pour expliquer que la récursion est intentionnelle.

Je serais ravi d'échanger quelques lignes supplémentaires de code banal maintenant pour une meilleure facilité de maintenance et un dépannage plus facile plus tard.

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

Oui, il est sûr jusqu'à ce que vous entrez un code incorrect chemin plusieurs milliers de fois.

0

Chaque recherche de temps() échoue, vous créez une instance de recherche() sur votre pile d'appel. Comme dans ce cas, il invite l'utilisateur à entrer une entrée, je suppose que l'utilisateur est susceptible d'abandonner longtemps avant que cela déborde votre pile, donc je suppose que le danger est minime ici. Mais si vous aviez une application qui a été essayée à nouveau en cas d'échec ou qui est passée à l'élément suivant dans une liste potentiellement longue, vous pourriez déborder la pile avec cette approche.

Je suggérerais une meilleure approche serait de mettre le bloc try/catch à l'intérieur de votre boucle while, et de passer à travers la boucle à nouveau en cas d'échec au lieu de faire un appel récursif. Quelque chose comme - ATTENTION - non testé le code suggéré:

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."); 
    } 
} 
Questions connexes