【问题标题】:Java abstract classes which throw抛出的 Java 抽象类
【发布时间】:2013-06-11 20:22:02
【问题描述】:

如果我有一个具有以下功能的抽象类 -

abstract class A{
    void foo(String s) throws Exception{
        throw new Exception("exception!");
    }
}

然后是另一个扩展抽象类并实现自己版本的 foo 的类 -

class B extends A{
    void foo(String s){
        //do stuff that does *not* throw an exception
    }
}

这会产生问题吗?具体在以下测试用例中 -

Collection<A> col = new Collection<A>();
B b = new B();
col.add(b);
for(A a : col){
    a.foo();
}

我做了一些测试,似乎没有任何问题,但我不明白为什么调用 B 的 foo 而不是 A 的

【问题讨论】:

  • 有了封装就不需要知道哪个类实现了方法。

标签: java exception abstract throw


【解决方案1】:

因为Polymorphism

因为在运行时Collection 中的实际对象类型是B,所以调用了B.foo()

基本上,如果您将子类型 object 分配给超类 reference,则运行时多态性会确保子类型的 一个实例方法被调用,即如果它当然被覆盖。如果不是,则调用回退到超类版本。

什么是有效的方法覆盖?

一个被覆盖的方法必须有

  • 相同的方法签名
  • 协变返回类型(可以返回子类型)
  • 不得抛出更广泛的检查异常 (适用于您的问题和@Dgrin91 的评论,即仅仅因为被覆盖的方法承担了一些风险(抛出异常)并不意味着覆盖方法也应该这样做;因此,它可能根本不会抛出任何异常)
  • 不得使用限制较少的访问修饰符(可以将protected设为public但不能设为private)

【讨论】:

  • 对,但问题是方法不同。一个抛出异常,另一个不抛出。多态性如何解释这一点?
  • 只有foo(String s) 计入方法签名。
【解决方案2】:

这不是问题——事实上,一种常见的做法是在未实现功能的基类中抛出异常,然后用未抛出的东西覆盖实现。一旦你重写了一个方法,基类的方法就不会被调用。

这样做的一个缺点是,如果您的异常恰好是已检查的(而不是“运行时”)类型,用户将需要捕获它。一个常见的解决方案是抛出未经检查的异常。

当然如果抛出异常的唯一目的是表明功能没有实现,最好在对应的方法abstract上做标记,让Java编译器捕捉到可能的违规行为。

【讨论】:

  • 另外,您可能会默认抛出 UnsupportedOperationException,但这只是人为设计的。
【解决方案3】:

正如另一张海报所指出的,这种行为是由于多态性而发生的。

您的集合被声明为 A.B 的元素,声明为扩展 A,是 A。您可以将 B 类型的元素添加到集合(需要 A 的实例)这一事实证实了这一点.

您的 A.foo 实现会引发异常,如果已调用,则确实会引发异常。另一方面,B 覆盖方法 foo,不抛出任何异常。由于您添加到集合中的实例是 B 之一,因此 B.foo 会被调用。它不会改变您的 for 循环将实例声明为 A 类型(这是有效的,因为 B 是-a A)。

您观察到的行为是预期的。

为了更好地理解,您可能需要创建:

class C extends A {}

并向集合中添加一个 C 实例。迭代 C 的 foo 将委托给父类 (A),然后按预期抛出异常。

【讨论】:

    【解决方案4】:

    您可以在不声明 throws 的情况下覆盖方法。这对于使用具体类的调用者很有用,例如使用 B 类的人不需要尝试捕获,因为该方法的实现不会抛出任何东西。

    Jon Skeet 在这里提供了更详细的解释:Inheritance , method signature , method overriding and throws clause

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-12-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多