不会引发检查的异常并将其转换为RuntimeException

时间:2019-01-06 15:33:04

标签: java exception

这是怎么回事?

为什么IOException(RemoteException)的受检查子级被转换为RuntimeException?

摘录自here

import java.rmi.RemoteException;

class Thrower {
    public static void spit(final Throwable exception) {
        class EvilThrower<T extends Throwable> {
            @SuppressWarnings("unchecked")
            private void sneakyThrow(Throwable exception) throws T {
                throw (T) exception; // something interesting 
            }
        }
        new EvilThrower<RuntimeException>().sneakyThrow(exception);
    }
}

public class ThrowerSample {
    public static void main( String[] args ) {
        Thrower.spit(new RemoteException("go unchecked!"));
    }
}

1 个答案:

答案 0 :(得分:3)

  

这是怎么回事?

此代码规避了Compile-Time Checking of Exceptions

为什么有用?

使用使用已检查异常的api并不总是很方便。

最著名的例子之一是JDBC。使用jdbc总是需要开发人员处理SQLException。但是通常您不知道应该如何处理该异常。

或者,如果您正在使用的库中,开发人员决定从Exception而不是RuntimeException继承其异常。


为什么IOExceptionRemoteException)的选中子转换为RuntimeException

它不会转换为RuntimeException

引发的异常为RemoteException

Exception in thread "main" java.rmi.RemoteException: go unchecked!

该代码段使用Java泛型“技巧”。如果没有@SuppressWarnings("unchecked")行,编译器将生成未经检查的强制转换警告。

拼图43

该代码段是Java Puzzlers: Traps, Pitfalls, and Corner Cases的第43个难题的解决方案之一:

// Don’t do this - circumvents exception checking!
public static void sneakyThrow(Throwable t) {
    Thread.currentThread().stop(t); // Deprecated!!
}
  

可以编写在功能上等效于sneakyThrow的方法   而不使用任何不推荐使用的方法。实际上,至少有两种方法可以做到这一点。   其中之一仅在5.0版及更高版本中有效。你能写这样的   方法?它必须用Java而不是JVM字节码编写。您不得更改   客户端编译后的方法。您的方法不一定是完美的:   如果不能抛出Exception的一两个子类,则可以接受。

本书中使用泛型的解决方案:

// Don’t do this either - circumvents exception checking!
class TigerThrower<T extends Throwable> {
    public static void sneakyThrow(Throwable t) {
        new TigerThrower<Error>().sneakyThrow2(t);
    }
    private void sneakyThrow2(Throwable t) throws T {
        throw (T) t;
    }
}

关于本书中此解决方案的说明:

  

警告是编译器告诉您可能正在开枪的方式   在脚上,事实上你是。未经检查的强制转换警告会告诉您   有问题的演员表不会在运行时检查。当您不受检查时   发出警告,修改程序以消除它,或者说服自己   演员不能失败

     

总而言之,虚拟机未强制执行Java的异常检查   机。它是一种编译时工具,旨在使编写正确的代码更容易   程序,但可以在运行时规避。为了减少曝光,请勿   忽略编译器警告。


另请参见:

@SneakyThrows