代码之家  ›  专栏  ›  技术社区  ›  Troskyvs

Jdk未能编译在Runnable内部引发异常的代码

  •  0
  • Troskyvs  · 技术社区  · 2 年前

    我试图从Runnable对象中抛出异常,如下所示:

      class ExceptionRunnable implements Runnable {
        @Override
        public void run() throws Exception {
          throw new Exception("ExceptionRunnable");
        }
      }
    

    编译错误:xxx。ExceptionRunnable.run()没有实现java.lang.Runnable.run(。被覆盖的run()没有抛出java.lang.InterruptedException。

    这真的很奇怪,我在扔 new Exception run 函数,但编译器说我并没有抛出任何东西。我在windows上使用jdk1.8。

    如何处理?

    1 回复  |  直到 2 年前
        1
  •  3
  •   Kaan    2 年前

    编译代码时:

    class ExceptionRunnable implements Runnable {
        @Override
        public void run() throws Exception {
            throw new Exception("ExceptionRunnable");
        }
    }
    

    编译器显示以下错误:

    java: run() in ExceptionRunnable cannot implement run() in java.lang.Runnable
      overridden method does not throw java.lang.Exception
    

    为什么?因为您要覆盖的方法- Runnable.run() -有这个签名(注意没有 throws 条款):

    void run()
    

    要解决第一个问题,请从此更改代码:

    public void run() throws Exception {
    

    以便签名匹配:

    public void run() {
    

    进行更改后,您将发现下一个编译器错误:

    java: unreported exception java.lang.Exception; must be caught or declared to be thrown
    

    这意味着您自己的代码正在抛出 Exception 它既没有被捕获,也没有在throws子句中声明。您已经发现不能将它添加到throws子句中,尽管这是您最初尝试做的 run() 方法,如下所示:

    @Override
    public void run() {
        try {
            throw new Exception("ExceptionRunnable");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    

    另一种选择是投掷 RuntimeException ,如下所示,但您应该 只有 这样做是有目的的,充分理解在代码中引入未检查的异常意味着什么。

    @Override
    public void run() {
        throw new RuntimeException("ExceptionRunnable");
    }
    
        2
  •  2
  •   Cheng Thao    2 年前

    看起来以前也问过类似的问题: Java : How to override a method and throw exception?

    抛出RuntimeException是否符合您的要求?

      class ExceptionRunnable implements Runnable {
        @Override
        public void run() {
          throw new RuntimeException("ExceptionRunnable");
        }
      }
    
        3
  •  0
  •   Alexander Ivanchenko    2 年前

    根据 方法覆盖 不能声明抛出 检查型异常 (或他们的超级类型 Throwable )在重写子类中的方法时未由父级声明的。

    引用 Language specification :

    如果m2具有 抛出条款 提到任何 已检查异常 类型, 那么m1必须有一个throws子句,或者 出现编译时错误

    当孩子有不太安全的行为时,其父母也会表示 Liskov substitution principle ,声明期望父实例的客户端代码应该能够在不知情的情况下使用其子实例。因为在子实例的行为不太安全的情况下,客户端将无法使用适合父实例的代码来处理它。

    超级型 Exception 已检查 (即编译器应确保在任何可能发生的情况下都能正确处理)和方法 run() 没有声明要扔任何 已检查异常 ,因此无法覆盖 run() 包括 例外 throws

    您可以包括任何类型的 未检查的异常 投掷 的结束 run() 。下面的代码是有效的,可以编译:

    class MyRunnable implements Runnable {
        @Override
        public void run() throws RuntimeException {
            // todo
        }
    }
    

    全部的 检查型异常 应该在内部处理代码可能抛出的 run() 并且不能传播到调用者:

    class MyRunnable implements Runnable {
        @Override
        public void run() throws RuntimeException {
            try {
                Thread.sleep(1_000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    

    注: 避免向声明 throw 以及避免抓到像 例外 可抛出 ,这是个坏习惯。尽可能具体