2013-05-16 2 views
6

У меня есть интерфейсреализация интерфейса запускает различные исключения

public interface DataDAO { 
    public void doSomething() throws Exception; 
} 

Допустим, что существует две реализации, одна, которая использует базу данных для получения данных и другой, который использует WebService.

public class DataDAOJdbc implements DataDAO { 
    public void doSomething() throws Exception { 
     //Implement 
    } 
} 

public class DataDAOWebService implements DataDAO { 
    public void doSomething() throws Exception { 
     //Implement 
    } 
} 

Как вы уже видите, проблема заключается в создании супер общего исключения. Поскольку обе реализации должны поднять один и тот же вид исключения.

Реализация Jdbc действительно только повышает позволяет говорить SQLException, в то время как реализация Webservice только повышает IOException.

Вопрос в том, как я могу сделать интерфейс более элегантным, поэтому я фиксирую правильное исключение?

Первое, что я, хотя создавал свое собственное исключение, и объявить его на уровне интерфейса

public interface DataDAO { 
    public void doSomething() throws MyCoolException; 
} 

И тогда, конечно, реализовать accordinly.

Вопрос в том, имеет ли это смысл? Я никогда не создавал свои собственные исключения, поэтому я не уверен, что это имеет смысл или нет. Кроме того, что я должен учитывать при создании MyCoolException?

+0

Как насчет того, чтобы вдохнуть весну и обернуть их в RuntimeExceptions. –

+0

@ AjayGeorge хорошо, я хочу, чтобы эти исключения обрабатывались на верхнем уровне, поэтому для них исключение RuntimExceptions не подходит для меня, исправьте меня, если я ошибаюсь :) –

+0

Ну, вы могли бы подклассировать RuntimeExceptions, а затем создать [DataAccessException] (http : //static.springsource.org/spring/docs/3.0.x/javadoc-api/org/springframework/dao/DataAccessException.html), как весной. –

ответ

4

Первое, что я, хотя и создаю свое собственное исключение, и объявляю его на уровне интерфейса (...), имеет ли это смысл?

Да, это действительно имеет смысл, и я думаю, что это лучший способ справиться с этими ситуациями.

я приведу пример стартового для этого (в зависимости от текущего кода):

public class MyCoolException extends Exception { 
    public MyCoolException() { 
    } 
    public MyCoolException(String message) { 
     this.message = message; 
    } 
} 

public interface DataDAO { 
    public void doSomething() throws MyCoolException; 
} 

public class DataDAOJdbc implements DataDAO { 
    public void doSomething() throws MyCoolException { 
     //Implement 
     try { 
     } catch (SQLException e) { 
      //handle the exception 
      logger.error("Error!", e); 
      //throw your custom exception 
      throw new MyCoolException(e.getMessage()); 
     } 
    } 
} 

public class DataDAOWebService implements DataDAO { 
    public void doSomething() throws MyCoolException { 
     //Implement 
     try { 
     } catch (IOException e) { 
      //handle the exception 
      logger.error("Error!", e); 
      //throw your custom exception 
      throw new MyCoolException(e.getMessage()); 
     } 
    } 
} 
+1

Хм, это ничто, но я бы рекомендовал обернуть исключение причины (а не строку сообщения) с помощью «MyCoolException» и ждать, чтобы зарегистрировать всю историю, когда будет обработано «MyCoolException». –

+1

Я абсолютно согласен с Полом, и я даже дошел до того, что это самое важное, что нужно учитывать при написании собственного исключения (* особенно *, если оно предназначено для обертывания другого исключения): без первоначальной причины вы теряете * много * информации, которая может быть абсолютно необходима при отладке любых проблем. –

+0

@PaulBellora Я согласен с вами, поэтому я сказал, что это базовый пример и регистрирует исключение, прежде чем реконструировать настраиваемое исключение. –

2

Вы можете использовать общий тип для определения интерфейса брошенный:

public interface DataDAO<E extends Throwable> { 
    public void doSomething() throws E; 
} 

Тогда ваши Реализации будут выглядеть следующим образом:

public class DataDAOJdbc implements DataDAO<JDBCException> { 
    public void doSomething() throws JDBCException { 
     //Implement 
    } 
} 

public class DataDAOWebService implements DataDAO<WebServiceException> { 
    public void doSomething() throws WebServiceException { 
     //Implement 
    } 
} 

Однако это имеет тот недостаток, что вы больше не может обрабатывайте все исключения таким же образом, если только вы не поймаете Exception (что в значительной степени отрицает всю точку).

+2

Но, предполагая, что OP хочет кодировать интерфейс, а не реализацию, это вообще не поможет вызовам сайтов. –

+0

@PaulBellora хороший момент, у вас есть идея лучше? –

+0

Этот подход разрушает полиморфизм. Следует использовать специальное исключение. – Mikhail

1

это имеет смысл?

Да, это так. Объявив, что doSomething выбрасывает определенное проверенное исключение, вы сигнализируете вызывающим абонентам метода, что им нужно только поймать и обработать это конкретное исключение. Объявив простой throws Exception, вызывающим абонентам будет предложено поймать и обработать все Exception с, которые включают даже исключения времени выполнения, такие как NullPointerException.

Что следует учитывать при создании исключения MyCoolException?

Это может быть столь же простым, как следующие:

public final class MyCoolException extends Exception { 

    public MyCoolException(Throwable cause) { 
     super(cause); 
    } 
} 

Так что ваш заказ исключение будет просто выступать в качестве обертки для исключения причин, какой бы она ни была. Если возможно, вы можете добавить сообщение с дополнительной информацией, которая может быть полезна для отладки. Когда поймано MyCoolException, вы можете развернуть его, вызвав getCause(), или передать его в вызов фреймворка ведения журнала (его стек будет включать в себя исключение причины).

Смежные вопросы