Ste*_*n C 10
下面的链接/部分编号取自 Java 语言规范的 Java 11 版本。
根据JLS 8.4.3.1:
“
abstract方法声明将方法作为成员引入,提供其签名(第 8.4.2 节)、结果(第 8.4.5 节)和 throws 子句(如果有)(第 8.4.6 节),但不提供实现(第 8.4 节) .7).没有的方法abstract可以称为具体方法。 ”
根据JLS 9.4:
“默认方法是在带有
default修饰符的接口中声明的实例方法。它的主体总是由一个块表示,它为实现该接口的任何类提供默认实现而不覆盖该方法。 默认方法与具体方法不同 ( §8.4.3.1),它们在类中声明,并且来自 私有接口方法,既不继承也不重写。”
所以根据这个分类法,实际上有 4 种方法:
请注意,JLS 8.4.3.1 没有提及final或static区分抽象方法和具体方法。
这些修饰符不能与abstract关键字一起使用。这意味着是static或final必须是具体方法的方法。这加强了 8.4.3.1 对具体方法的定义。
Java 语言规范 (JLS)第 8.4.3.1 节中将抽象方法定义为:
抽象方法声明将方法作为成员引入,提供其签名(第 8.4.2 节)、结果(第 8.4.5 节)和 throws 子句(如果有)(第 8.4.6 节),但不提供实现(第 8.4 节) .7)。
实际上,抽象方法是定义了签名但未提供实现的任何方法。例如,接口中的方法和abstract抽象类中用关键字限定的方法都是抽象方法:
public interface Foo {
void someAbstractMethod();
}
public abstract class Bar {
public abstract someAbstractMethod();
// ...
}
Run Code Online (Sandbox Code Playgroud)
根据 JLS第 8.4.3.1 节,具体方法定义为:
不抽象的方法可以称为具体方法。
实际上,这意味着提供了实现的任何方法:
public FooImpl implements Foo {
@Override
public void someAbstractMethod() {
// ... some implementation ...
}
}
Run Code Online (Sandbox Code Playgroud)
默认方法在 JLS第 9.4 节中定义:
默认方法是在具有默认修饰符的接口中声明的实例方法。它的主体总是由一个块表示,它为任何实现接口的类提供默认实现而不覆盖方法。默认方法不同于在类中声明的具体方法(第 8.4.3.1 节),也不同于既不继承也不重写的私有接口方法。
同一部分还增加了:
接口可以声明
static方法,这些方法在不引用特定对象的情况下被调用。static接口方法不同于默认方法,默认方法是实例方法。
默认方法是为特定目的而创建的。在 JDK 8 中,函数式接口被添加到 Java 中。这需要更新接口以包含功能方法,但这样做将要求这些接口的所有现有实现(包括在第 3 方库和框架中)都需要提供实现。相反,Java 团队引入了默认方法,这些方法是提供默认实现的接口方法,当覆盖类没有提供实现时使用该实现。
这不应该用作抽象类的替代品。它旨在用于特定目的,并且应该用于该目的。
在实践中,默认方法是使用default关键字创建的:
public interface Foo {
public default void someMethod() {
// ... some default implementation ...
}
}
Run Code Online (Sandbox Code Playgroud)
这个默认实现可以在具体的子类中被覆盖:
public class FooImpl implements Foo {
@Override
public void someMethod() {
// ... some overriding implementation ...
}
}
Run Code Online (Sandbox Code Playgroud)
此外,根据 JLS第 9.4.1.1 节,可以使用super由接口名称限定的关键字在具体子类中访问方法的默认实现(默认方法的主体):
可以使用包含
super由超级接口名称限定的关键字的方法调用表达式(第 15.12 节)访问覆盖的默认方法。
例如:
public class FooImpl implements Foo {
@Override
public void someMethod() {
Foo.super.someMethod();
}
}
Run Code Online (Sandbox Code Playgroud)
接口名称用作限定符,因为一个类可以实现多个接口(或者一个接口可以扩展多个接口)。有关更多信息,请参阅在 Java 中显式调用默认方法。