Ты прав.
Исключение должно быть на том же уровне абстракции, где используется. Это причина того, что в java 1.4 Throwable поддерживается цепочка исключений. Нет смысла выдавать исключение FileNotFoundException для службы, которая, например, использует базу данных, или для службы, которая не зависит от хранилища.
Это может быть так:
public abstract class Data {
public abstract String read() throws DataUnavailableException;
}
class DataFile extends Data {
public String read() throws DataUnavailableException {
if( !this.file.exits() ) {
throw new DataUnavailableException( "Cannot read from ", file );
}
try {
....
} catch( IOException ioe ) {
throw new DataUnavailableException( ioe );
} finally {
...
}
}
class DataMemory extends Data {
public String read() {
// Everything is performed in memory. No exception expected.
}
}
class DataWebService extends Data {
public string read() throws DataUnavailableException {
// connect to some internet service
try {
...
} catch( UnknownHostException uhe ) {
throw new DataUnavailableException( uhe );
}
}
}
Имейте в виду, что если вы программируете с учетом наследования, вам следует тщательно проектировать для конкретных сценариев и тестировать реализации с этими сценариями. Очевидно, что если будет сложнее кодировать библиотеку общего назначения, потому что вы не знаете, как она будет использоваться. Но в большинстве случаев приложения ограничены определенной областью.
Должно ли ваше новое исключение быть Runtime или Checked? Это зависит от того, что общее правило заключается в том, чтобы выбрасывать Runtime для ошибок программирования и проверять исправимые условия.
Если исключение можно избежать путем правильного программирования (например, NullPointerException или IndexOutOfBounds), используйте Runtime
Если исключение вызвано тем, что какой-то внешний ресурс не контролируется программистом (например, сеть не работает) И есть что-то, ЧТО можно сделать (показать сообщение о повторной попытке через 5 минут или что-то в этом роде), тогда проверенное исключение следует использовать.
Если исключение не контролируется программистом, но НИЧЕГО не может быть сделано, вы можете использовать RuntimeException. Например, вы должны записать файл, но файл был удален, и вы не можете создать его заново или повторить попытку, после чего программа может завершиться сбоем (вы ничего не можете с этим поделать), скорее всего, во время выполнения.
См. Эти два элемента из Effective Java:
- Использовать проверенные исключения для восстанавливаемых условий и исключения во время выполнения для ошибок программирования
- Бросить исключения, соответствующие абстракции
Надеюсь, это поможет.