Заменить проверенное исключение на исключение во время выполнения?

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

try {
    file.read();
} catch (IOException e){
    throw new RuntimeException(e); 
}

У этого есть несколько недостатков, но больше всего меня раздражает то, что мое исключение во время выполнения будет содержать вложенную трассировку стека. По сути, я хотел бы повторно выдать "IOException" как RuntimeException (или "IORuntimeException") с исходным сообщением и трассировкой стека, чтобы я мог избежать бесполезной вложенной трассировки стека. "Факт", что я перебросил исключение где-то посередине, кажется мне просто бесполезным шумом.

Это возможно? Есть ли библиотека, которая делает это?

6 ответов

Project Lombok позволяет полностью отключить отмеченные исключения.

Продолжайте из моего комментария. Вот статья, которая должна пролить свет на эту проблему. Оно использует sun.misc.Unsafe отбрасывать исключения, не оборачивая их.

class IORuntimeException extends RuntimeException {

    final IOException ioex;

    public IORuntimeException(IOException ioex) {
        this.ioex = ioex;
    }

    @Override
    public String getMessage() {
        return ioex.getMessage();
    }

    @Override
    public StackTraceElement[] getStackTrace() {
        return ioex.getStackTrace();
    }

    //@Override
    // ...
}

( Здесь доступен полный класс, созданный макросом Eclipse "Generate Delegate Methods".)

Использование:

try {
    ...
} catch (IOException ioex) {
    throw new IORuntimeException(ioex);
}

Если вы рассматриваете использование Unsafe в другом ответе (я рекомендую нет, но в любом случае), другой вариант - использовать дженерики для создания проверенного исключения с помощью этой злой пары методов (из http://james-iry.blogspot.co.uk/2010/08/on-removing-java-checked-exceptions-by.html):

   @SuppressWarnings("unchecked")
   private static <T extends Throwable, A> 
     A pervertException(Throwable x) throws T {
      throw (T) x;
   }


   public static <A> A chuck(Throwable t) {
      return Unchecked.
        <RuntimeException, A>pervertException(t);
   }

Вы также можете проверить com.google.common.base.Throwables.getRootCause(Throwable) и просто распечатать его (корневую) трассировку стека.

Похоже, что вы на самом деле нужно проверить исключения

Начиная с Java 8 есть другой способ:

try {
  // some code that can throw both checked and runtime exception
} catch (Exception e) {
  throw rethrow(e);
}

@SuppressWarnings("unchecked")
public static <T extends Throwable> RuntimeException rethrow(Throwable throwable) throws T {
    throw (T) throwable; // rely on vacuous cast
}

* Более подробная информация здесь.

Другие вопросы по тегам