Exceptions werfen und fangen

Posted October 18, 2007

Ein weiterer schwerwiegender Unterschied zwischen Java und C# ist die Behandlung von Exceptions. In Java muss jede Exception, die geworfen wird, bereits in der Methodendefinition enthalten sein und außerdem müssen alle Exceptions(Ausnahmen) auch wirklich in der aufrufenen Methode behandelt werde, also entweder weitergeworfen oder gefangen werden.

In verschiedenen Fällen führt sowohl in C# alsauch in Java ein naives Programmieren zu Code, der eher wenig mit Exceptions arbeitet - vor allem, wenn der Programmierer zu optimistisch ist und immer nur den korrekten Programm-Ablauf vor Augen hat. Dabei gibt es viele Szenarien, in denen Ausnahmen auch ganz bewusst geworfen und behandelt werden um auf Fehler möglichst schnell und auch eindeutig reagieren zu können. Dass entspricht in etwa der berühmten "Regel des Reparierens: Wenn das Programm scheitert, soll es das lautstark und so früh wie möglich tun.", die ein Teil der so genannten UNIX-Philosophie ist.

Ein kleines Beispiel in Java nutzt Exceptions aus, allerdings sollte man den Code nicht einfach kopieren, da Exceptions wesentlich mehr sinn machen, wenn man entsprechende Ableitungen für verschiedene Situationen bildet und nicht immer die unspezifische Exception nutzt.

private String dataToString(Collection<String> data) throws Exception {
    StringBuilder sb = new StringBuilder();
    for (String s : data) {
        if (s == null) {
            throw new Exception("Data should not be null");
        }
        sb.append(s);
        sb.append('\n');
    }
    return sb.toString();
}
 
private void saveToFile(File file) throws Exception {
    if (file.exists() && !file.canWrite()) {
        throw new Exception("File exists already and could not be overwritten.");
    }
    Writer wr = new FileWriter(file);
    BufferedWriter br = new BufferedWriter(wr);
    try {
        String s = dataToString();
        br.write(s);
    } finally {
        br.close();               
    }
}
 
private File chooseFile() throws Exception {
    JFileChooser chooser = new JFileChooser();
    int result = chooser.showSaveDialog(this);
    switch (result) {
        case JFileChooser.ERROR_OPTION:
            throw new Exception("An Error ocurred");
        case JFileChooser.CANCEL_OPTION:
            throw new Exception("Saving Cancelled by User");
        default:
            return chooser.getSelectedFile();
    }
}        
 
/* . . . . */
saveButton = new JButton();
saveButton.setText("Save");
saveButton.addActionListener(new ActionListener() {
    public void actionPerformed(ActionEvent e) {
        try {
            File file = chooseFile();
            saveToFile(file);
        } catch(Exception e2) {
            errorLabel.setText(e2.getMessage());
            errorLabel.setVisible(true);
        }
    }
});

(originally posted on 2007-10-19)