接口 (Java)

在Java编程抽象类型

接口(英语:Interface),在Java编程语言中是一个抽象类型英语Abstract_type(Abstract Type),它被用来要求(Class)必须实现指定的方法,使不同类的物件可以利用相同的界面进行沟通。接口通常以interface来宣告,它仅能包含方法签名(Method Signature)以及常量宣告(变量宣告包含了 staticfinal),一个接口不会包含方法的实现(仅有定义)。在Java 8之后,被放宽为允许定义默认方法——在接口具体实现方法,和类静态方法。

接口无法被实例化,但是可以被实现。一个实现接口的类,必须实现接口内所描述的所有方法,否则就必须宣告为抽象类英语Abstract_class(Abstract Class)。另外,在Java中,接口类型可用来宣告一个变量,他们可以成为一个空指针,或是被绑定在一个以此接口实现的物件。

其中一个使用接口的优势是,可以利用他们模拟多重继承,类在JAVA中不允许多重继承,所有在JAVA中的类必须而且仅能有一个父类,而java.lang.Object(JAVA类型系统中最顶层的类型)是唯一一个例外。

JAVA的类可以被实现许多个接口,然而一个接口则无法实现其他的接口。

概观

接口被用来统一类的共通行为,当不同的类需要进行资讯共享时,是不需要特别去建立类间的关系。举例来说,一个人(Human)及一只鹦鹉(Parrot)都会吹口哨(whistle),然而HumanParrot不应该为Whistler的子类,最好的做法是令他们为Animal的子类,而他们可以使用Whistler的接口进行沟通。

还有一种接口的使用方法,则是当一个物件有实现特定接口时,我们使用它是不需要知道它的类,例如,一个事物因为口哨的噪音影响到其他人,对于其他人而言,就不需要知道噪音来源是来自人还是鹦鹉,因为他们可以确定,一个会吹口哨的事物正在吹口哨。举一个更实际的例子,排序算法可能会期待物件的类型是可以被Comparable的,于是它只需要知道物件的类型可以被以某种方式进行排序即可,这与物件的类无关。whistler.whistle()将会调用物件的实现方法whistle,而不需要知道物件是以哪个类来实现Whistler

例如:

interface Bounceable {
      void setBounce();  // 注意分號
                         // 介面的方法(method)是公開(public)、抽象(abstract)、永遠不會是最尾端的型別(final)
                         // 把它們想成只是個模型,所以沒有任何方法有被實現
                         
      //以下语法在Java 8之后的版本是可行的,之前则编译错误
      default void defaultMethod(){ 
          System.out.println("defaultMethod");
          setBounce(); //可以调用同接口的实例方法
      }
  }

使用方法

接口的宣告

下列的语法为接口的宣告方式:

[存取修飾] interface 介面名稱 [extends 其他的介面] {
        常數宣告
        抽象方法宣告
}

接口的主体包含着抽象方法,但所有方法在接口内(定义上)都是抽象(Abstract)方法,所以abstract的关键字在接口内则不被需要。由于接口代表着一个对外行为的集合,所以任何方法在接口内都是public(公开的)。

所以,一个简单的接口可以这么写

public interface Predator {
       boolean chasePrey(Prey p);
       void eatPrey(Prey p);
}

接口内的成员皆为静态(static)、final及公开(public),反之,他们可以成为任何类或接口的类型[1]

实现一个接口的语法,可以使用这个公式:

... implements 介面名稱[, 其他介面, 其他的..., ...] ...

类可以用来实现接口,举例来说

public class Lion implements Predator {

        public boolean chasePrey(Prey p) {
               // programming to chase prey p (specifically for a lion)
        }

        public void eatPrey (Prey p) {
               // programming to eat prey p (specifically for a lion)
        }
}

如果一个类实现了一个接口,而没有实现接口的所有方法,则它必须被标注为abstract(抽象类)。一个抽象类的子类必须实现它未完成的方法,假如该项子类仍不会实现接口的所有方法,那么该项子类依然需要被标注为abstract

类可以同时实现多项接口

 public class Frog implements Predator, Prey { ... }

接口通常被使用在Java编程语言,用来做回调函数使用[2] 。Java并不允许方法作为参数传递使用,因此,其中一个解决办法则是可以定义一个接口,把这个接口当成方法的参数,以此来使用该项物件的方法签名。

子接口

接口可以被延伸为数个不同的接口,可以使用上述所描述的方法,举例来说:

 public interface VenomousPredator extends Predator, Venomous {
         //介面主體
 }

以上的程序片段是合法定义的子接口,与类不同的是,接口允许多重继承,而PredatorVenomous 可能定义或是继承相同的方法,比如说kill(Prey prey),当一个类实现VenomousPredator的时候,它将同时实现这两种方法。

示例

有些泛用的Java接口可供参考:

  • Comparable 拥有一个方法compareTo,用以描述两个物件是否相等,或是其中一个物件大于另外一个物件。泛型允许已经实现的类,其物件可以用来互相比较。
  • Serializable 是一个标记接口(marker interface),没有任何方法或是成员,仅有一个空的主体,它被用来表示一个类可以被序列化。它的Javadoc描述了他是如何运作,而且不需要被强制编程。

另见

参考文献

  1. ^ The Java Language Specification. [2013-01-18]. (原始内容存档于2012-02-29). 
  2. ^ Java World. [2013-01-18]. (原始内容存档于2008-09-16). 

外部链接