Sembra che tu abbia due opzioni in mente:
-
createPath
inghiotte l'eccezione e l'applicazione si arresta in modo anomalo da qualche parte su NullPointerException
.
- In realtà, il modo corretto per farlo è lanciare un
RuntimeException
o un Error
o una sottoclasse di uno di essi.
- Aggiungi
throws IOException
all'intera callchain fino a main
e lascia che l'applicazione si blocchi con IOException
.
Ma l'effettiva intenzione dietro le eccezioni controllate (o le eccezioni in generale) è diversa:
- Aggiungi
throws IOException
al callchain fino al chiamante che sa cosa fare nel caso in cui un file non possa essere creato, e quel chiamante prenderà il IOException
e lo gestirà.
Considera il seguente esempio:
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Scanner;
public class App {
private Scanner reader;
public App() {
reader = new Scanner(System.in);
}
public String getPathFromUser() {
System.err.print("Enter a path: ");
return reader.nextLine();
}
public Path createPath(String name) throws IOException {
return Files.createFile(Paths.get(name));
}
public Path promptForPath() {
while (true) {
String path = getPathFromUser();
try {
return createPath(path);
} catch (IOException e) {
System.err.printf("Unable to create %s (%s)\n", path, e);
continue;
}
}
}
public static void main(String[] args) {
App app = new App();
Path path = app.promptForPath();
// do stuff with path
}
}
Qui main
chiama promptForPath
che a sua volta chiama createPath
.
-
promptForPath
sa come gestire quel IOException
(chiede all'utente un percorso diverso), quindi non deve essere contrassegnato con throw IOException
.
-
createPath
non sa come gestirlo, quindi deve essere throw IOException
.
-
main
non sa come gestirlo - ma non è necessario perché promptForPath
lo ha già gestito.
È meglio inquinare i metodi nello stack di chiamate con le clausole throws
o uglify createPath
con try
... catch
?
Queste cose sono solo brutte e ingombranti quando vengono messe nel posto sbagliato. Quando vengono inseriti nel posto giusto, invece di essere un brutto inquinamento, possono essere effettivamente inseriti come parte della logica.
Il try
... catch
nella createPath
nella domanda è un brutto odore di codice - è chiaro che è lì per nascondere un problema. Il try
... catch
nel mio promptForPath
, d'altra parte, non è brutto perché sta gestendo un problema.
Allo stesso modo, throws IOException
nei metodi di livello superiore è brutto - perché il tuo main
dovrebbe lanciare un IOException
? Ma nei metodi più bassi che ottengono il percorso ha senso (" questo metodo si occupa dei percorsi e potrebbe incontrare un percorso non esistente ") in modo che non siano brutti - sono parti utili delle firme.
Un'altra cosa da considerare: se bolla le eccezioni fino in fondo, stai solo sostituendo un'eccezione con un'altra. Non sono sicuro che valga la pena il lavoro. Ma se lo stai solo ribollendo fino al punto in cui puoi gestirlo, la qualità della tua applicazione è migliorata - invece di andare in crash, ad esempio, stai notificando all'utente che il percorso che hanno inserito non è valido e gli chiedi di inserire un nuovo. Questo è un comportamento preferibile dalla parte dell'utente, e rende utile il refattore.