根据JLS的“8.1.1.1”,我们有:
如果满足以下任一条件,则C类具有抽象方法:
•C的任何成员方法(第8.2节) - 无论是声明的还是继承的 - 都是 抽象。
•任何C的超类都有一个用包访问声明的抽象方法, 并且没有方法可以从C或来自覆盖抽象方法 C的超类
有趣的是,为什么我们这里有第二种选择。特别是,为什么我们有完全“包访问”。那么“公共”还是“受保护”的方法呢?
答案 0 :(得分:3)
从大多数私有到最开放的顺序,java修饰符转到:
子类不能继承另一个包中父类的包方法。因此,根据规则1,从这样的父类继承的类将不是抽象的。因此,第二条规则用于解决子类从抽象父类继承并且无法提供抽象包方法的实现的情况。 / p>
这是一个荒谬的情况,我绝不会期望在任何地方的任何地方看到这一点。但是语言必须完全指定,否则你最终可能会遇到一个奇怪的错误,它允许实例化具有未定义方法的类。
答案 1 :(得分:0)
这可能意味着protected
和public
也是提供包访问权限的声明。 private
方法不是,它们也不是抽象的。
答案 2 :(得分:0)
是的,我认为你是对的。 第二种选择仅涉及一个特定情况: 特殊子类与其超类的包不同。
例如,
package superpackage;
public abstract class SuperFoo {
abstract void foo();
}
package subpackage;
import superpackage.SuperFoo;
public abstract class SubFoo extends SuperFoo {}
请注意,此类应声明为abstract,否则我们会出现编译错误。
在这种特殊情况下,我们没有"继承foo方法"作为继承需要 SubFoo类与SuperFoo位于同一个包中。 有关更多详细信息,请参阅JLS中的8.4.8节。
尽管如此,这个班仍然包含" foo"方法(按定义),因此应使用抽象关键字标记。
此外,我们可以通过属于" superpackage"的另一个具体类扩展我们的SubFoo类。封装
例如,
package subclass;
import subpackage.SubFoo;
public class SecondSubFoo extends SubFoo {
@Override
void foo() {}
}
注意:
1)事实是公共和受保护的方法属于定义的第一项,因为它们是继承的,并且不需要第二项定义。
2)如果包装访问方法位于同一个包中,它们也属于第一个定义项,因此也不需要第二个定义项。
3)另一方面,另一个包中的包访问方法不属于定义的第一项,因为它们不是继承的(参见JSL第8.4.8节中抽象方法的继承定义)和因此,他们需要第二项定义。