美文网首页IT技术篇
Java基础教程(17)--接口

Java基础教程(17)--接口

作者: 游戏原画设计 | 来源:发表于2019-01-15 18:34 被阅读0次

     就像类一样,接口也是引用类型。它可以包含常量,方法签名,默认方法,静态方法和嵌套类型。在接口中,只有默认方法和静态方法有方法体。但不同于类,接口无法实例化,它只能被类实现或被其他接口继承。

    一.定义接口

      接口的定义由修饰符、关键字interface、接口名、extends关键字(接口可以继承并且支持多继承)和若干继承的父接口(如果有的话)以及接口体组成,语法如下(方括号表示可选内容):

    publicinterfaceDoIt[extendsInterface1,Interface2]{voiddoSomething(inti,doublex);intdoSomethingElse(String s);}

    public修饰符代表这个接口可以在任何地方使用。如果没有指定接口是public的,那么这个接口只能在定义这个接口的包中使用。

    一个接口可以继承其他接口,就像一个类可以继承另外一个类一样。不同的是,一个类只能继承一个父类,而一个接口可以继承多个接口。

    接口体包含了若干个抽象方法,从Java8之后,接口中还可以包含默认方法和静态方法。抽象方法后直接跟分号,没有大括号,因为抽象方法不包含实现。默认方法使用default关键字定义,静态方法使用static关键字定义。接口中的所有方法都默认且必须是public的,因此可以省略方法前的public。

    此外,接口可以包含常量声明。在接口中定义的所有常量都默认是public,static和final的,因此可以省略这些修饰符。

    二.实现接口

    要实现接口,需要在定义类时在类名后面使用implements关键字,然后跟着以逗号分隔的要实现的接口列表。按照惯例,如果类既继承了父类,又实现了接口,implements语句应该放在extends语句后面。

    下面定义了一个USB接口:

    publicinterfaceUSB{voidread();voidwrite();}

      如果一个类实现了某个接口,则它必须实现这个接口中所有的抽象方法。假设现在我们要定义一个U盘类,它需要实现USB接口,那么它必须实现USB接口中定义的read和write方法:

    publicclassUDiskimplementsUSB{@Overridepublicvoidread(){        System.out.println("Reading UDisk...");    }publicvoidwrite(){        System.out.println("Writing UDisk...");    }}

      当定义了一个新的接口时,实际上就是定义了一个新的引用数据类型。如果定义了一个接口类型的变量,则这个变量只能引用实现了这个接口的类的实例。例如:

    USB usb =newUDisk();

    三.接口中的静态方法

      和类一样,接口也可以有静态方法。不同的是,在类中,既可以通过定义静态方法的类及其子类调用静态方法,也可以通过该类和子类的实例调用静态方法(可以但不推荐);在接口中,则只能通过定义静态方法的接口去调用静态方法,而不能通过实现它的类及其实例调用静态方法。接口的静态方法仅对于接口本身可见。例如下面的接口:

    publicinterfaceBar{staticvoidfoo(){        System.out.println("I'm a static method.");    }}

      可以通过Bar.foo()的形式调用这个静态方法。假设有个BarImpl实现了这个接口,那么无论是BarImpl.foo()或new BarImpl().foo()都会产生编译错误,因为这个静态方法对它们来说是不可见的。

    四.默认方法

      从Java8之后,可以为接口中的方法提供一个默认实现。使用关键字default来表示这是一个默认方法。例如:

    publicinterfaceComparable{defaultintcompareTo(T other){return0;    }}

      当然,这里的默认方法并没有太大用处,因为Comparable的每一个实现类都要覆盖这个方法。不过有些情况下,默认方法可能很有用。如果希望在发生鼠标点击事件时得到通知,就要实现一个包含5个方法的接口:

    publicinterfaceMouseListener{voidmouseClicked(MouseEvent event);voidmousePressed(MouseEvent event);voidmouseReleaseed(MouseEvent event);voidmouseEntered(MouseEvent event);voidmouseExited(MouseEvent event);}

      大多数情况下,我们只关心其中的一两个事件。可以将所有方法声明为默认方法,这些默认方法什么也不做:

    publicinterfaceMouseListener{defaultvoidmouseClicked(MouseEvent event){}defaultvoidmousePressed(MouseEvent event){}defaultvoidmouseReleaseed(MouseEvent event){}defaultvoidmouseEntered(MouseEvent event){}defaultvoidmouseExited(MouseEvent event){}}

    这样一来,实现这个接口时,只需要覆盖真正关心的事件方法就可以了。

    默认方法可以调用其他的默认方法、静态方法和抽象方法。例如,Collection接口可以定义一个便利方法:

    publicinterfaceCollection{intsize();defaultbooleanisEmpty(){returnsize() ==0;    }}

    这样在实现Collection接口时就不用操心isEmpty方法了。

    默认方法的一个重要用法是“接口演化”。以Collection接口为例,这个接口作为Java的一部分已经很多年了。后来,在Java8中,又为这个接口增加了一个stream方法。假设stream不是一个默认方法,那么其他已经实现了Collection接口的类将不能编译,因为要实现接口就必须实现接口所有的抽象方法。这样一来,就要修改其他所有已经实现了Collection接口的类的代码,这显然不是我们愿意看到的。

    不过,如果我们为stream方法提供默认实现,那么问题就迎刃而解了。其他已经实现了Collection接口的类不用做任何修改,就可以通过编译,而且还可以在这些类的实例上调用stream方法。如果真的有部分类需要重新定义stream方法而不是使用默认的stream方法,那么工作量也会小很多。

    下面来讨论默认方法的继承问题。当一个接口继承一个包含默认方法的接口时,可以执行以下操作:

    不做任何修改,完全继承父接口的默认方法;

    重新声明这个默认方法,使它变成抽象方法;

    重写这个默认方法。

      执行第1种和第3种操作时,接口的实现类既可以选择使用默认的实现,也可以覆盖这个默认的方法。但执行第2种操作时,则必须实现这个抽象方法。

    出处:https://www.cnblogs.com/maconn/

    相关文章

      网友评论

        本文标题:Java基础教程(17)--接口

        本文链接:https://www.haomeiwen.com/subject/mvlddqtx.html