2017-01-05 3 views
3

Я пытался использовать метод handleException, который может взять объект исключения и список допустимых классов исключений, чтобы проверить, является ли исключение приемлемым и может быть повторено.Как передать список параметров класса?

void handleException(Exception e, String... acceptableExceptionNames) 
     throws MyException { 

    boolean isRetryable = false; 

    for(String acceptableExceptionName: acceptableExceptionNames) { 
     try { 
     if (Class.forName(acceptableExceptionName).isInstance(e)) { 
      isRetryable = true; 
      break; 
     } 
     } catch (ClassNotFoundException e1) { 
     continue; 
     } 
    } 

    if (isRetryable) { 
     // log retryable 
    } else { 
     // log error 
    } 

    throw new MyException(isRetryable, "Failed"); 
    } 

Параметр прохожу в это String... classNames вместо Class<? extends Exception> classes, потому что если я делаю что-то вроде этого:

void handleException(
    Exception e, 
    Class<? extends Exception>... acceptableExceptions) 
     throws MyException { 
    for (Class acceptableException : acceptableExceptions) { 
     if (e instanceOf acceptableException) {} 
    } 
} 

В среде IDE будет сетовать unknown class acceptableException

Любой знает, если есть способ пройти Class<?>? Или лучший способ избежать использования String classNames и Class.forName()?

+0

Вы не можете использовать общий тип в Исключениях! – Michael

+2

Когда вы используете varargs, тип 'acceptExceptions' является' Class [] '. – chrylis

+0

Почему вы попробовали 'e instanceOf приемлемыеExceptions' с массивом классов? Вы продемонстрировали, что знаете, как перебирать массив и вызывать метод Class.isInstance в другом фрагменте. – user2357112

ответ

6

acceptableExceptions не Class, это Class[]. Вы можете сохранить свой оригинальный дизайн, хотя, и просто использовать Class объекты непосредственно вместо того, чтобы создавать их из строк:

void handleException 
     (Exception e, Class<? extends Exception>... acceptableExceptionNames) 
     throws MyException { 

    boolean isRetryable = false; 

    for(Class<?> acceptableExceptionName: acceptableExceptionNames) { 
     if (acceptableExceptionName.isInstance(e)) { 
      isRetryable = true; 
      break; 
     } 
    } 

    if (isRetryable) { 
     // log retryable 
    } else { 
     // log error 
    } 

    throw new MyException(isRetryable, "Failed"); 
} 

EDIT:
Как примечание стороны, этот код может быть значительно короче, используя Java 8 в потоки :

void handleException 
     (Exception e, Class<? extends Exception>... acceptableExceptionNames) 
     throws MyException { 

    boolean isRetryable = 
     Arrays.stream(acceptableExceptionNames).anyMatch(x -> x.isInstance(e)); 

    if (isRetryable) { 
     // log retryable 
    } else { 
     // log error 
    } 

    throw new MyException(isRetryable, "Failed"); 
} 
+2

Зачем заменять класс 'with' Class '? Вы больше не ограничиваете типы классов. – Andreas

+0

@ Аndreas, потому что 'Class 'приведет к предупреждению о куче-загрязнении через' приемлемыеExceptionNames', хотя я не совсем понимаю, почему это предупреждение происходит. – Turing85

+0

Какое «предупреждение о предостережении от кучи»? Мой Eclipse не дает такого предупреждения. – Andreas

-1

Используйте следующие проверки

for (Class<? extends Exception> exceptionClass : acceptableExceptions) { 
    if (exceptionClass.isInstance(e)) { 
     // it is your exception 
    } 
} 
1

на мой взгляд, это легче сделать, если, выполняя простые сравнения строк, как это:

private void handleException(Exception ex, String... acceptableException) { 
    for (int x = 0; x < acceptableException.length; x++) { 
     String[] exceptionClass = ex.getClass().toString().split("."); 
     if (!acceptableException[x] 
       .equals(exceptionClass[exceptionClass.length - 1])) { 
      /* Exception Not Acceptable */ 
     } 
    } 

    /* Exception Acceptable */ 
} 
2

Вы не хотите проверять, является ли e экземпляром Class[], что и является acceptableExceptions, но если это экземпляр , то один из классов, на которые ссылается массив acceptableExceptions.

Для этого вам необходимо выполнить итерацию, и вам необходимо использовать метод отражения Class.isInstance(Object obj). Как говорит javadoc:

Этот метод является динамическим эквивалентом языка Java instanceof.

Чтобы избежать предупреждений компилятора, вам также необходимо добавить @SafeVarargs к вам метод, если он static или final. В противном случае вам нужно добавить @SuppressWarnings("unchecked") как к методу, так и к вызывающему абоненту.

@SuppressWarnings("unchecked") 
void handleException(Exception e, Class<? extends Exception>... acceptableExceptions) throws MyException { 
    boolean acceptable = false; 
    for (Class<? extends Exception> acceptableException : acceptableExceptions) 
     if (acceptableException.isInstance(e)) { 
      acceptable = true; 
      break; 
     } 
    if (acceptable) { 
     // code here 
    } 
} 
+0

К сожалению, '@ SafeVarargs' не применяется к неконкретным методам экземпляра с varargs. Если это необходимо, вы получите ['@SuppressWarnings (" unchecked ")'] (http://stackoverflow.com/questions/12462079/potential-heap-pollution-via-varargs-parameter). – dhke

+0

@dhke Ты прав. В моем тестировании я использовал метод static. – Andreas

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