今天遇到一个问题,代码(后面各个版本的代码都是基于此代码进行变更的)如下:
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(); } }
它的打印结果中是:
method f 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中可以查看到出错消息为:
Exception IOException is not compatible with throws clause in Type2.f()
对于这个现象,在《Java 解惑》的迷题37中,有如下的描述:
一个方法可以抛出的受检查异常集合是它所适用的所有类型的声明要抛出的受检查异常集合的交集,而不是合集。
也就是说,在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)则不适用。
关于什么是 Checked Exception ,什么是 Unchecked Exception,可以查看http://czj4451.iteye.com/blog/1851825
相关推荐
对于一个类实现两个接口,而这两个接口又有同名方法,C#中的处理方式如下: using System; using System.Collections.Generic; using System.Text; namespace Super { class Program { static void Main(string[] ...
在Java中,接口是一种强制实现特定方法的合同,它可以被类来实现,以确保类具备某些预定义的行为。 标题提到的是通过继承接口和多态来实现矩形类(Rectangle)和正方形类(Square)对对角线长度计算的功能。接口`...
/**一个类实现了两个接口,两个接口中的方法相同,这个类在覆写的时候就会出现冲突*/ class D: B,C{ //当下面两个方法同时存在的时候,就会报方法相同的冲突 override fun x(): Int { return super
- **接口**提供了一种规范,强制类实现指定的方法,一个类可以实现多个接口,实现多继承。 - **多态**允许更灵活的代码编写,提高了程序的扩展性和适应性,可以在不关心具体类型的情况下处理对象。 在实际开发中,...
2. **解决命名冲突**:如果不同接口中有同名成员,显式实现可以确保为每个接口提供独特的实现,避免混淆。 然而,显式实现有一些限制。比如,如果类没有在基类列表中明确列出接口,那么在子类中无法直接显式实现该...
在上述代码中,`ListEntry` 类同时实现了 `ICloneable` 和 `IComparable` 两个接口。需要注意的是,显式接口成员的实现不能使用任何访问修饰符(如 public 或 private),也不能使用 `abstract`, `virtual`, `...
方法覆盖是指子类重写父类的方法,而方法重载是指同一个类中定义多个同名的方法,但参数不同。 四、继承 继承是Java中的一个重要概念,指的是一个类继承另一个类的所有成员变量和方法。继承的主要特点是: * 子类...
4. **重载(Overloading)**:当在同一个类中定义两个或多个同名方法,但参数列表不同(参数数量、类型或顺序不同)时,这就是方法重载。Java通过参数列表来决定调用哪个方法,而不是返回类型或方法体。 5. **重写...
当一个类实现了一个接口,它就必须提供接口中所有方法的具体实现。多个类可以实现同一个接口,这样就形成了接口多态。例如,我们可以定义一个"可打印"接口,然后让打印机类和日志记录类都实现这个接口,这样无论处理...
如果类同时继承了两个接口,这两个接口中有同名的默认方法,那么必须在子类中明确重写这个方法,以解决冲突。 总结来说,Java接口是设计模式中的关键元素,它促进了代码的模块化和可扩展性。理解并熟练运用接口,...
`Collection`接口有两个主要的子接口:`List`和`Set`。`List`接口要求元素有序且允许重复,而`Set`接口则不允许重复元素,通常保持无序。此外,`Queue`接口用于实现队列操作,`Deque`接口则扩展了队列的功能,支持...
一个类可以实现多个接口,使用 implements 关键字,语法如下:public class 类名称 implements 接口名称 { /* Bodies for the interface methods */ /* Own data and methods. */ }。在实现接口时,需要注意该类必须...
假设我们有两个接口`InterfaceA`和`InterfaceB`,它们都定义了一个名为`NAME`的常量,现在我们希望在一个类`MultipleInterfaces`中同时实现这两个接口,并解决常量冲突。代码如下: ```java interface InterfaceA {...
在这个实例中,所有创建的类都将实现两个接口,这将展示如何通过接口实现多态性。同时,为了进一步展示Java的灵活性,我们在最底层的类中创建了一个**内部类(Inner Class)**,内部类可以访问外部类的所有成员,...
2. **接口实现**:类可以通过`implements`关键字实现一个或多个接口,并提供接口中所有抽象方法的实现。一个类可以同时实现多个接口,实现多继承的效果。例如: ```java class Dog implements Animal { public ...
在Windows系统中,虽然不同目录下可以有同名文件,但在Java中,同名的类不能放在同一个文件夹内。创建包非常简单,只需在Java源文件的开头使用`package`关键字指定包名,如`package com.svse.bookstore;`。包名通常...
例如,一个`Animal`父类和`Dog`、`Cat`两个子类,每个类都有自己的`sound()`方法,通过多态实现不同的叫声。 4. **源代码压缩包** 压缩包内的源代码可能是实现上述概念的实例。学生可能编写了一个主程序,通过创建...
接口的主要目的是为不相关的类提供通用处理服务,由于C#中只允许属性结构中的单继承,一个类只能继承一个父类,所以接口是让一个类具有两个以上的基类的唯一方式。 接口的定义和声明方式与类相似,使用关键字...
当我们谈论“C++规定与类同名的函数就是拷贝构造函数”时,实际上是指一个类中定义的与类名相同且参数为该类类型的函数,这就是拷贝构造函数。 拷贝构造函数是一种特殊的构造函数,用于初始化一个新对象为已有对象...