- 接口的定义
•Java接口是抽象方法的集合,其定义语法为:
访问权限控制符 interface 接口名 [extends 接口列表] {
常量;
抽象方法;
内部类;
}
例如
public interface Mother { //创建Mother接口
int WEIGHT=10; //创建WEIGHT常量
public void eat(); //创建eat方法
}
在定义接口时有三点注意事项:
①接口的访问控制符只有两种:public和友好的(默认类)
可以看到,除了public和友好的之外,其他两种访问控制符使用时均报错,错误原因为:接口不合法,只允许public(友好的因为为默认未写出)
②接口中的抽象方法必须为public访问权限控制符,不能为其它控制符。这一点是由于java对接口的定义导致的,故不详细说明。
- 接口的继承
与类相似,接口也能继承,通过extends关键字可以使自定义的接口实现继承,但需要注意以下两点:
①接口只能继承父接口,不能继承抽象类和普通类。
Son接口继承Father接口
Son接口继承Mother类时程序报错:Mother类不能成为Son接口的超接口,接口只能继承接口
②接口弥补了Java单一继承的缺点(Java中的类只能继承一个父类),即接口可以继承多个父接口,它们之间用英文逗号隔开。
由于java中的单继承特性,一个类如果想同时具有多个类的方法及属性,只能用连续继承的方法来做到,这样子会使得代码量非常大,并且可读性很差,而接口则不同,通过extends关键词继承,并且由逗号连接多个父接口,操作十分简单。
- 接口的实现
从之前的接口中必须有抽象方法的定义,我们可以知道接口其实是无法调用方法的,因此接口中方法的实现需要用到类。
类通过implements关键字实现接口,Java中的类只能是单继承,但却可以实现多个接口以弥补Java类单继承的不足,其语法如下:
访问控制符 修饰符 class 类名 implements 接口1 [,接口2, ……] {
变量;
方法;
public interface Father { /*
int weight=10; *
public abstract void eat(); *
} */创建Father父接口
public class Daughter implements Father { //创建Daughter类实现Father接口
public void eat() {
System.out.println("吃东西"); //实现eat方法
}
}
}
同时,在实现接口时需要注意两点:
①如果一个类实现了一个接口,但没有实现接口中的所有抽象方法,那么这个类必须是abstract类。
public interface Mother {
public void sleep();
public void eat();
}
//创建Mother接口并创建sleep,eat方法
public class Son implements Mother{
public void eat()
}
//创建Son类实现Mother接口,并且只实现eat方法
public interface Father {
public void sing();
public void speak();
}
//创建Father接口并创建sing,speak方法
public class Daughter implements Father {
public void speak() {
System.out.println("说话");
}
public void sing() {
System.out.println("唱歌");
}
//创建Daugher类实现Father接口,并实现了sing,speak方法(父类中的全部方法)
在执行的时候,我们会发现只有Son类出了问题,编译器会提醒我们要同时实现Mother类的另一个功能。
为什么一定要实现一个接口的全部功能才行呢?其实也并不是这样。只是这时候的Son类身为一个普通类,在他准备实现Mother接口时,他就默认继承了Mother的所有方法以及属性,而在他实现某个方法的时候实质上是在对接口中的抽象方法进行重写,则原有的抽象方法就不再是抽象方法了,反之,其没有实现的抽象方法被原样继承,因此Son类中会含有抽象方法。根据我们对抽象类的定义,此时Son类成为了一个抽象类,而其修饰符前并没有abstract关键字,因此冲突了导致程序报错 。如果要解决这个问题,假设我们并不打算让这个类实现接口的全部方法,我们需要将其变为abstract类。
程序不再报错
如果多个接口中定义了相同的抽象方法,则在实现类中只实现其中一个即可:
相比前一点,这个还是很容易理解的,因为这些抽象方法相同,而类同时实现两个接口的话,对这个方法进行实现的时候相当于把两个接口中该相同抽象方法都重写了,所以只需要实现其中一个就行了。
- 接口中的常量
①•接口实现类可以直接使用接口中的常量:
②接口实现类所实现的多个接口中有常量名相同的常量,则在实现类中不能直接使用,必须使用类名来确定到底调用哪个接口中的常量:
public interface Mother {
int AGE=1;
}
//创建Mother接口及其中的常量AGE
public interface Father {
int AGE=0;
}
//创建Father接口及其中的常量AGE
public class Son implements Mother,Father{
public static void main(String[] args) {
System.out.println(AGE);
}
}
//创建Son类实现Mother,Father接口,并且输出AGE
在这段代码中,两个被实现的接口有一个同名常量,而实现类输出的常量并没有进行标注
编译器报错,并表明AGE常量模糊不清,这说明我们应该将AGE的归属接口表示出来,在常量之前加上其所在的接口名并加上".”后,程序正常运行。
- 接口中的方法
•Java8以前版本中规定,接口中所定义的方法只能是抽象方法,从Java8开始,接口中可以添加一个或多个由default关键字修饰的非抽象方法,该方法又称为扩展方法,该默认方法将由接口实现类创建的对象来调用,如下例:
public interface IMammal { //Imammal接口
void move(); //抽象方法
public default void eat() {
System.out.println("哺乳动物正在吃......"); //创建了由default关键字修饰的有
//方法体的非抽象方法
}
}
所以要区别java版本,并不一定接口中只能定义抽象方法,但是由default关键字修饰的非抽象方法,接口本身仍然无法调用 。
但与此不同的是,从Java8开始,接口中可以添加一个或多个由static关键字修饰的非抽象方法,该方法将由接口或其实现类直接调用,如下例:
interface IMammal { //IMammal接口
void move(); //move抽象方法
static void eat() {
System.out.println("哺乳动物正在吃......"); //由static修饰的非抽象方法
}
}
接口中的静态方法实现类无法继承,默认方法实现类可以继承,如下例: