现在有这么一些场景,如下面表格所述,假设具体类及接口的权限修饰符都为`public`
类C1有成员方法A和B
public class C1 {
public void A(){
System.out.println("C1.A()");
}
public void B(){
System.out.println("C1.B()");
}
}
接口I1有抽象方法C以及默认方法D
public interface I1 {
void C();
default void E(){
System.out.println("I1.default.E()");
}
}
接口I2有抽象方法A
public interface I2 {
void A();
}
接口I3有默认方法A以及默认方法C
public interface I3 {
default void A(){
System.out.println("I3.default.A()");
}
default void C(){
System.out.println("I3.default.C()");
}
}
接口I4有抽象方法A以及默认方法B
public interface I4 {
void A();
default void B(){
System.out.println("I4.default.B()");
}
}
(与上表相同,复制到这里为了方便阅读)
场景一:定义类MainTest继承类C1实现接口I1,因为类C1以及接口I1中所有的方法签名都不一样,所以调用时不考虑方法签名重复问题
public class MainTest extends C1 implements I1{
public static void main(String[] args) {
C1 c1 = new C1();
c1.A();
c1.B();
I1 i1 = new MainTest();
i1.C();
i1.E();
}
@Override
public void C() {
System.out.println("I1.C()");
}
}
结果:
C1.A()
C1.B()
I1.C()
I1.default.E()
(与上表相同,复制到这里为了方便阅读)
场景二:定义类MainTest继承类C1实现接口I2,I2抽象方法A与类成员方法A签名重复,优先使用父类方法
public class MainTest extends C1 implements I2{
public static void main(String[] args) {
C1 c1 = new C1();
c1.A();
c1.B();
I2 i2 = new MainTest();
i2.A();
}
}
结果:
C1.A()
C1.B()
C1.A()
(与上表相同,复制到这里为了方便阅读)
场景三:定义类MainTest继承类C1实现接口I3,接口I3默认方法A签名与类C1成员方法A签名重复,优先使用父类成员方法
public class MainTest extends C1 implements I3{
public static void main(String[] args) {
C1 c1 = new C1();
c1.A();
c1.B();
I3 i3 = new MainTest();
i3.A();
i3.C();
}
}
结果:
C1.A()
C1.B()
C1.A()
I3.default.C()
(与上表相同,复制到这里为了方便阅读)
场景四:定义类MainTest继承类C1实现接口I4,接口I4方法A、B的签名分别与类C1的方法A、B签名重复,优先使用父类方法
public class MainTest extends C1 implements I4{
public static void main(String[] args) {
C1 c1 = new C1();
c1.A();
c1.B();
I4 i4 = new MainTest();
i4.A();
i4.B();
}
}
结果:
C1.A()
C1.B()
C1.A()
C1.B()
场景五:假如一个接口I1的抽象方法、默认方法都与接口I2的抽象方法、默认方法的签名一样,当实现的多个接口中有相同签名的方法时,必须在实现类中通过重写方法解决冲突问题,否则无法通过编译,在重写的方法中可以通过 接口名.super.方法名(); 的方式显示调用需要的方法
interface I1 {
void A();
default void B(){
System.out.println("I1.default.B()");
}
}
interface I2 {
void A();
default void B(){
System.out.println("I2.default.B()");
}
}
public class MainTest implements I1, I2{
public static void main(String[] args) {
MainTest mainTest = new MainTest();
mainTest.B();
mainTest.A();
}
@Override
public void B() {
I2.super.B();
}
@Override
public void A() {
System.out.println("A(),I don't know who I am");
}
}
结果:
I2.default.B()
A(),I don't know who I am
总结
1.当继承的父类和实现的接口中有相同签名的方法,优先使用父类的方法
2.当实现的多个接口中有相同签名的方法时,必须在实现类中通过重写方法解决冲突问题,否则无法通过编译,在重写的方法中可以通过 接口名.super.方法名(); 的方式显示调用需要的方法
3.当接口的父接口中也有同样的默认方法时,就近原则调用子接口的方法。