【java基础】一个类所实现的两个不同的接口中,有同名的方法,怎么知道实现的是哪个接口中的方法

今天遇到一个问题,代码(后面各个版本的代码都是基于此代码进行变更的)如下:

public interface Type1 {
	void f();
 
	void f1();
 
	void f11();
}
public interface Type2 {
	void f();
 
	void f2();
 
	void f22();
}
public class IFTest implements Type1, Type2 {
 
	@Override
	public void f2() {
	}
 
	@Override
	public void f22() {
	}
 
	@Override
	public void f() {
		System.out.println("method f");
	}
 
	@Override
	public void f1() {
 
	}
 
	@Override
	public void f11() {
 
	}
}

 当时有过这样一个疑问:Type1和Type2中都有一个f()方法,那么IFTest中的f()方法到底实现的是Type1中的f()呢,还是Type2中的f()呢?其实,这种疑问是多余的,因为IFTest中的f()既是Type1中的f()也是Type2中的f()。因为既然IFTest这个类没有发生编译错误,那就说明它既实现Type1也实现了Type2,也就是说Type1中的f()与Type2中的f()在IFTest中是相安无事的。可以通过以下的JUnit测试用例来看一下:

public class IFTestTest {
 
	/**
	 * Test method for {@link com.rainbow.util.demo.iftest.IFTest#f()}.
	 * 
	 * @throws IOException
	 */
	@Test
	public void testF() throws Exception {
		Type1 ift = new IFTest();
		Type2 ift2 = new IFTest();
		ift.f();
		ift2.f();
	}
}

 它的打印结果中是:

  1. method f  
  2. method f  

-------------------------------------------分隔线-------------------------------------------

 

上面这个问题的变种:

将Type1中的f()的返回值修改为int,将Type2中的f()的返回值修改为boolean,那么又会是什么结果呢?

public interface Type1 {
	int f();
 
	void f1();
 
	void f11();
}
public interface Type2 {
	boolean f();
 
	void f2();
 
	void f22();
}
public class IFTest implements Type1, Type2 {
 
	@Override
	public void f2() {
	}
 
	@Override
	public void f22() {
	}
 
	@Override
	public void f() {
		System.out.println("method f");
	}
 
	@Override
	public void f1() {
 
	}
 
	@Override
	public void f11() {
 
	}
}

在我意料之中,此时IFTest这个类在编译时就报错了, 在Eclipse中,将鼠标移至IFTest的f()上,查看一下,出错消息为:

The return type is incompatible with Type2.f()

 这也就说明了,如果两个接口有同名的方法,但是它们的返回值不一样,那么,是无法用一个类同时来实现这两个接口的。

 

-------------------------------------------分隔线-------------------------------------------

 

上面这个问题的变种:

 

将Type1中的f()声明为抛出IOException,将Type2中的f()声明为抛出CloneNotSupportedException,那么又会是什么结果呢?

public interface Type1 {
	void f() throws IOException;
 
	void f1();
 
	void f11();
}

 

public interface Type2 {
	void f() throws CloneNotSupportedException;
 
	void f2();
 
	void f22();
}
public class IFTest implements Type1, Type2 {
 
	@Override
	public void f2() {
	}
 
	@Override
	public void f22() {
	}
 
	@Override
	public void f() throws CloneNotSupportedException, IOException {
		System.out.println("method f");
	}
 
	@Override
	public void f1() {
 
	}
 
	@Override
	public void f11() {
 
	}
}

我本来以为上面的IFTest是可以正常通过编译的。但是,结果却是残酷的,在Eclipse中可以查看到出错消息为:

  1. Exception IOException is not compatible with throws clause in Type2.f()  

对于这个现象,在《Java 解惑》的迷题37中,有如下的描述:

  1. 一个方法可以抛出的受检查异常集合是它所适用的所有类型的声明要抛出的受检查异常集合的交集,而不是合集。  

 也就是说,在IFTest的f()上声明的异常只能是在Type1和Type2的f()上都声明过的异常。因为此示例中,Type1抛出的是IOException,而Type2抛出的是CloneNotSupportedException,即Type1与Type2的f()所抛出的异常是没有交集的,因此,IFTest的f()是无法声明抛出任何异常的。

如果像下面这样修改一下:

public interface Type1 {
	void f() throws IOException, CloneNotSupportedException;
 
	void f1();
 
	void f11();
}
public interface Type2 {
	void f() throws CloneNotSupportedException;
 
	void f2();
 
	void f22();
}

那么,就可以将IFTest的f()修改为声明抛出 ClonseNotSupportedException了,因为这个时候Type1和Type2的f()都声明了 ClonseNotSupportedException,这个异常就是它们抛出的异常的交集:

public class IFTest implements Type1, Type2 {
 
	@Override
	public void f2() {
	}
 
	@Override
	public void f22() {
	}
 
	@Override
	public void f() throws CloneNotSupportedException {
		System.out.println("method f");
	}
 
	@Override
	public void f1() {
 
	}
 
	@Override
	public void f11() {
 
	}
}

当然,对于这一点,一定要注意一下,仅仅是针对 受检查的异常(Checked Exception) 才起作用的,对于非受检查的异常(Unchecked Exception)则不适用。

转载地址:

https://blog.youkuaiyun.com/rainbow702/article/details/50519167

<think>嗯,用户的问题是关于Java中当一个实现多个接口时,如果这些接口同名方法,该如何解决冲突。这个问题我之前学过一点,但得仔细想想才能回答正确。 首先,我得回忆一下Java接口方法冲突的规则。记得在Java 8之前,接口只能有抽象方法,所以实现必须覆盖所有方法同名方法的话,实现只需要提供一个实现就行,可能不会有冲突。但Java 8引入了默认方法,这时候如果两个接口同名的默认方法实现就必须解决冲突。 用户提供的引用里提到,可以通过覆盖方法或者使用super关键字指定某个接口的默认方法。比如引用[1]和引用[2]都提到,在实现中覆盖方法或者用super来选择。引用[4]中的例子也显示,如果不处理就会报错,所以必须明确解决。 另外,引用[3]提到C#可以显式实现接口方法,但Java没有这个特性。不过Java 8允许通过接口名.super.方法名来调用特定接口的默认方法,比如InterfaceA.super.method(),这在覆盖的时候使用。 解决方案应该分几种情况:如果接口都是抽象方法,那么实现必须自己实现;如果有一个接口提供了默认方法,另一个没有,可能没问题;如果两个接口都有默认方法,就必须在实现中覆盖,并选择调用哪个或者提供新的实现。 还要注意,如果两个接口方法签名不同(参数或返回不同),可能构成重载,不会有冲突。但如果方法签名相同,返回不同,就会导致编译错误,这种情况可能无法解决,必须修改接口设计。 总结一下,解决方案应该是:覆盖方法并提供新实现,或者用Interface.super.method()调用指定接口的默认方法。同时要分情况讨论不同接口方法的情况,比如是否都是默认方法,或者是否有抽象方法。 用户可能想了解具体的代码示例,所以需要给出例子说明如何覆盖和使用super。此外,可能还需要提到编译错误的情况,以及最佳实践,比如避免设计有冲突的接口,或者优先使用抽象等。 最后,生成的相关问题可能涉及性能、优化、应用场景,或者其他编程语言如何处理似问题,比如C#的显式实现,或者中间件冲突的解决方案,如引用[5]提到的路径更改等,但用户的问题集中在Java接口方法冲突,所以相关问题应围绕Java的解决方案展开。</think>### Java实现多个接口同名方法冲突的解决方案 当Java实现多个接口且存在同名方法时,需根据接口方法型(**抽象方法**或**默认方法**)分情况解决。以下是具体解决方案: --- #### **情况1:多个接口同名方法均为抽象方法** 此时实现必须**强制覆盖该方法**,提供唯一实现。 ```java interface A { void doSomething(); } interface B { void doSomething(); } class MyClass implements A, B { @Override public void doSomething() { System.out.println("统一实现"); } } ``` --- #### **情况2:多个接口中存在同名默认方法** 若多个接口定义了同名默认方法(使用`default`关键字),实现必须**显式覆盖冲突方法**,并通过`<接口名>.super.<方法名>`语法指定调用逻辑: ```java interface A { default void doSomething() { System.out.println("A的默认实现"); } } interface B { default void doSomething() { System.out.println("B的默认实现"); } } class MyClass implements A, B { @Override public void doSomething() { // 手动选择调用A或B的默认实现 A.super.doSomething(); // 调用A的默认方法 B.super.doSomething(); // 调用B的默认方法 } } ``` --- #### **情况3:混合抽象方法与默认方法** 若一个接口提供默认方法,另一个接口要求抽象方法实现仍需覆盖方法,但可复用默认实现: ```java interface A { default void doSomething() { System.out.println("A的默认实现"); } } interface B { void doSomething(); // 抽象方法 } class MyClass implements A, B { @Override public void doSomething() { A.super.doSomething(); // 直复用A的默认实现 } } ``` --- #### **其他注意事项** 1. **返回型冲突**:若同名方法返回型不兼容(如`int`与`String`),编译器直报错,需修改接口设计[^4]。 2. **最佳实践**:优先通过接口设计避免冲突,或使用**适配器模式**隔离不同接口的逻辑。 3. **编译规则**:Java强制要求实现解决默认方法冲突,否则编译失败[^2]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值