sto cercando di sbatterci la testa.
l'unica cosa che mi è venuta in mente, è usare la reflection.
ma ho dubbi che sia la strada giusta.

cmq:
codice:
private <T> void doExp(T t, String titolo, FileChooser.ExtensionFilter ext, List<Nota> list) {
    DirChooser dc = new DirChooser();
    Optional<File> file = dc.saveFile(getStage().getOwner(), titolo, ext);
    if (file.isPresent()) {
        try {
            DoExport de = (File f, List<Nota> l, String[] header) -> f.getPath(), ll, str;
            de.export(file.get(), list, new String[]{});

            Class<T> cl = (Class<T>) Class.forName(t.getClass().getName());
            Object obj = cl.getDeclaredConstructor().newInstance();
            Class[] params = new Class[2];
            params[0] = String.class;
            params[1] = List.class;
            Method method = cl.getDeclaredMethod("create", params);
            method.invoke(obj, file.get().getPath(), list);

        } catch (IOException | WriteException | ClassNotFoundException | NoSuchMethodException | IllegalAccessException | InstantiationException | InvocationTargetException ex) {
            GenericDialog.showDialog(ex.getMessage(), Alert.AlertType.WARNING);
        }
    }
}

ma parte dal presupposto che tutti i vari tipi di export abbiamo il metodo create (che nel mio caso è così e mi va bene che sia cosi).
inoltre, non tutti gli export hanno gli stessi parametri.
ad esempio quello per l'export in CSV ha anche un String[] per l'intestazione.
quindi così scritto non è cmq flessibile.