赞
踩
今天遇到一个问题,代码(后面各个版本的代码都是基于此代码进行变更的)如下:
- 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();
- }
- }
它的打印结果中是:
-------------------------------------------分隔线-------------------------------------------
上面这个问题的变种:
将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中可以查看到出错消息为:
对于这个现象,在《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)则不适用。
转载地址:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。