简单例子如下:
下面的例子定义了两个类,两个类都实现了flyanimal的接口。注意,一个接口可以同时定义多个公共方法。
interface Flyanimal{
void fly();
}
class Insect {
}
class Bird {
}
class Ant extends Insect implements Flyanimal {
public void fly(){
System.out.println(“Ant can fly”);
}
}
class Pigeon extends Bird implements Flyanimal {
public void fly(){
System.out.println(“pigeon can fly”);
}
}
public class InterfaceDemo{
public static void main(String args[]){
Flyanimal a=new Ant();
a.fly();
Flyanimal p= new Pigeon();
p.fly();
}
}
接口的意义在于类的规范化,如果程序代码需要修改添加新类,原有代码不需要修改。
实际上,java的接口的C++的多继承实现的是同一逻辑功能。java不只是多重集成,当出现需要多重集成描述的关系时,就采用接口。一个类可以实现多个接口。
接口里的函数的的修饰符一定是public astract,你可以写,也可以不写。但是不能写别的。
接口里成员变量的修饰符一定是public static final。也可以省略。但是不能写别的。
至于接口本身的修饰符,默认是abstract final。这两个无论写不写都有。但是可以选择写不写public,区别就在于外包是否可见了。
顺便讲解下关键字abstract。可以用来修饰类(抽象类)也可以用来修饰方法(抽象方法)。只要一个类中含有抽象方法。那它一定是抽象类。反之则不一定。如果在类中定义了抽象方法,就必须对类加上abstract修饰。不然就会编译错误。抽象类不能被实例化。
abstract class A{
public abstract void test();
}
那么问题就来了,既然有接口了,为什么要有抽象类呢?其实,两者从设计上的目的不同,抽象类是一组类的公共模版,而接口则是定义一组类的公共行为模式。
再顺便讲解下final关键字
(1)final修饰类,则该类不能被继承
(2)final定义变量,则变量已经赋值就不能修改。不过没必要定义时就赋值
(3)final定义方法,则说明该方法不能被重写。你也可以给一个private的方法加上final关键字。不过这样毫无意义。因为本来子类就看不见他。
最后讲一下标记接口
Java中常用的三个标记接口分别是:RandomAccess、Cloneable、Serializable,在查看JDK源码的时候,我们会经常发现这些接口的存在,它们不包含任何的方法.
Cloneable。clone方法是object的一个方法。但是,不是所有类都继承了object类就可以调用该方法。(虽然谁该方法是protected的)。必须要显示的加上上面标记接口的那句话。当然,你可以再程序中调用该接口并通过编译,但是,在运行中程序会报出CloneNotSupportedException异常。所以,给那些具备克隆能力的类标记上该接口是极为重要的。
RandomAccess。试想一下有两个类,一个类是java.util.ArrayList,一个类是java.util.LinkedList,他们都继承了List接口,所以都有get(index)来获取容器中某一个元素的方法。但是,你先染不愿意对任何List接口的对象调用get,因为LinnkedLIst不可避免会带来性能问题。那你如何遍历该List容器呢?这时候,就可以检查这个对象是否实现了RandomAccess接口,实现了就表示使用get方法不会带来性能问题。
Serializable 用于标记一个对象是否支持序列化。显然,这个问题,我们将在java序列化一章详细讲解。