2013-02-14 68 views
3

Java编译器如何知道java.lang.RuntimeException及其子类未被选中,因为它们从java.lang.Exception继承,这是一个检查的异常?我研究了代码,看起来不是类中的任何东西,它告诉编译器。Java如何知道RuntimeExceptions未被选中?

+0

因为它'知道'写在JLS中的内容,而不仅仅是类层次结构中的内容。 – EJP 2013-02-15 03:59:17

回答

8

因为它是在specification of the language # 11.1.1定义方式:

  • 未经检查的异常类是运行时异常类和错误类。
  • 检查的异常类是除未经检查的异常类以外的所有异常类。也就是说,检查的异常类是除了RuntimeException及其子类和Error及其子类之外的Throwable的所有子类。

所以它不是各种异常类的代码的一部分,它是编译器必须实现的兼容,仅是语言定义的一个惯例。

+0

建立在@assylias写道:所有的Java编译器必须检测到一个'java.lang.RuntimeException'正在使用,并做内部需要做的任何事情来从“checked”转到“unchecked”。源代码不会告诉编译器“我是一个未经检查的异常”,这是因为编译器知道RuntimeException类的全名并可以查找它们。 – 2013-02-14 16:42:37

1

事实上,它延伸RuntimeException就足够了。在编译期间,它知道类的层次结构是什么,所以如果它包含RuntimeException,则它未被选中。否则,它会被检查。请记住,checked/unchecked是一个编译器约束,而不是运行时约束,有办法让Java抛出检查从未被捕获的异常。例如,使用Proxy

public class ExceptionalInvocationHandler implements InvocationHandler { 

    @Override 
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { 
     throw new IOException("Take that, checked exceptions!"); 
    } 
} 

和接口:

public interface Example { 
    public void doSomething(); 
} 

,并创建一个代理,并调用它:

Example ex = (Example) Proxy.newProxyInstance(Example.class.getClassLoader(), 
    new Class[] { Example.class }, 
    new ExceptionalInvocationHandler()); 
ex.doSomething(); // Throws IOException even though it's not declared. 
+1

我知道它很简单,但编译器是如何知道它的? – 2013-02-14 16:24:06

+1

@DanielPereira因为它构造了一个类层次结构?如果你想要确切的实施细节,这不是要问的地方。看看OpenJDK的编译器源代码。 – Brian 2013-02-14 16:25:44

+1

为什么Stackoverflow不是一个问这个问题的地方?我认为这是一个编程问答网站。 – 2013-02-14 16:29:04