【问题标题】:Throwing an exception from an anonymous inner class's constructor从匿名内部类的构造函数中抛出异常
【发布时间】:2015-02-04 23:20:48
【问题描述】:

如何向匿名内部类的构造函数添加“抛出”?

class Foo {
  public Foo() throws Exception {
  }
}

因为这不起作用

 public static void main(String[] args) {
   Foo x = new Foo() {
     @Override
     public Foo() throws Exception {
     }
   }
 }

我正在尝试找出“抛出”的位置以抑制编译器警告。有没有办法在不使用 try/catch 块或创建单独的类的情况下做到这一点?

【问题讨论】:

  • 在我输入完之前不小心按了回车,我已经得到了-2。
  • 是的,有时人们会比你想象的更快更频繁地打你一巴掌,而且经常没有告诉你原因。

标签: java exception constructor anonymous-inner-class throws


【解决方案1】:

我不确定您要完成什么。请注意,匿名类永远不会有显式声明的构造函数。这是可以理解的,因为如果它有名字,它就需要有一个名字,因此不再是匿名的。

如果你想有一个构造函数可能抛出的类的匿名子类,这不是问题。

class Foo {
    Foo() throws Exception {
    }
}

void demo() throws Exception {
    Foo foo = new Foo() {  // might throw
    };
}

同样,如果你想用可能抛出的东西来初始化匿名类,你也可以这样做。请记住,匿名类的定义是表达式,因此只要它们被 try-catch 块包围或包含方法声明要抛出的异常,它们就可以抛出。

class Foo {
}

class Bar {
    Bar() throws Exception {
    }
}

void demo() throws Exception {
    Foo foo = new Foo() {
        Bar bar = new Bar();  // might throw
    };
}

【讨论】:

    【解决方案2】:

    您不能在匿名类上声明构造函数。

    来自 Java 语言规范,第 15.9.5.1 节,“匿名构造函数”:匿名类不能有显式声明的构造函数。

    如果您需要一个新的构造函数,请将类设为内部类(但不是匿名的),甚至是顶级类。

    【讨论】:

    • 如果我仍然想把它放在一个匿名的内部类中,我是否必须使用 try/catch 块,或者有其他方法吗?
    • 您所指的“它”是什么?构造函数?
    • 取决于您的代码是否实际抛出。由于 Foo 被声明为抛出,因此最好使用 try / catch 块。
    【解决方案3】:

    如果你真的需要强制匿名类的实例的一致性,你可以在一个工厂方法中创建它们,如果参数无效则抛出异常。这仅适用于接口的匿名实例,因为匿名类不能是方法的返回类型。

    一个完全没有意义的例子:

    public class AnonymousException {
    
        public static void main(String args) {
            newRunnable(42).run();
        }
    
        private static Runnable newRunnable(final int x) {
            if(x < 0) throw new IllegalArgumentException();
            return new Runnable() {
                @Override
                public void run() {
                    System.out.println("x=" + x);
                }
            };
        }
    }
    

    【讨论】:

      【解决方案4】:

      我正在尝试找出“抛出”的位置以抑制编译器警告。

      throws 无法做到这一点。匿名的语法不允许您在(隐式)构造函数上放置 throws 子句。 (隐式)构造函数隐式抛出您正在使用的所有超类构造函数。 (这取决于参数的数量和类型......)

      除此之外:即使它确实做到了,throws 子句也不会抑制我怀疑您遇到的编译错误。从根本上说,超类构造函数声明它可能抛出Exception 并添加throws 无法改变这一事实......没有某种方法来处理超类构造函数异常。

      有没有办法在不使用 try/catch 块或创建单独的类的情况下做到这一点?

      不,没有。

      而且我怀疑您尝试做的事情甚至不可能使用常规的超类/子类。例如:

      public class Foo {
          public Foo(int i) throws Exception { }
      }
      
      public class Bar extends Foo {
          public Bar(int i) {
              super(i);
          }
      }
      

      没有办法编译它,因为Bar 构造函数无法抑制或处理Foo 构造函数声明它抛出的异常。

      (这是有充分理由的。如果Foo(42) 确实抛出了异常,那么当异常到达Bar 构造函数时,它必须处理部分构造 Foo。这是不实际的,即使是这样,也是个坏主意。)

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-11-04
        • 2014-11-03
        • 2019-03-11
        • 2023-03-11
        • 1970-01-01
        • 2017-02-09
        • 1970-01-01
        • 2010-10-29
        相关资源
        最近更新 更多