一、接口语法
接口的创建
interface
//接口不能直接创建对象 public interface grammar { //定义的属性都是公有静态属性(默认也是) String name = ""; // private int num = 10;//报错。因为接口中只能定义公有静态属性 //定义的普通方法默认都是公有抽象方法 void m1();//抽象方法没有方法体 // public void A(){}//报错,因为接口中只能定义公有抽象方法,但是在新版本添加了一些方法能创建,后面介绍 }
接口的实现
除非实现接口的类是抽象类,否则该类要定义并实现接口中的所有抽象方法。
implements
public class A implements grammar{ //实现接口类必须重写接口的所有抽象方法,否则会报错 @Override public void m1() { } }
二、接口与抽象类异同
面试题:接口与抽象类的异同
相同点:
可作为引用类型
不能创建对象
都能使用object的方法
不同点:
接口中定义的属性默认为公有静态属性
接口中定义的普通方法默认为公有抽象方法
接口中不能定义构造方法和代码块
一个类只能继承一个抽象类,而一个类却可以(继承)实现多个接口。
三、接口的概念
接口时一种能力和约定。一般适用于使用多态,但是无法提取 is a 的关系来定义父类的情况,可以使用接口来定义某种能力,来实现多态.
例如:农民给动物喂水,然后肉食动物会捕猎,食草动物会吃草
农民给动物喂水,动物喝水是他们共同的能力,肉食动物喝水后会捕猎,捕猎属于肉食动物的能力;食草动物喝水后会吃草,而吃草属于食草动物的能力,
public interface hunt { //动物捕猎能力接口 void hunting(); } public interface eatGrass { //动物食草能力接口 void eatGrass(); } public abstract class Animal { //动物喝水 public abstract void drink(); } public class sleep extends Animal implements eatGrass{ @Override public void drink(){ System.out.println("sleep drink"); eatGrass(); } @Override public void eatGrass() { System.out.println("sleep eat Grass"); } } public class tiger extends Animal implements hunt{ @Override public void drink(){ System.out.println("Tiger drink"); hunting(); } @Override public void hunting() { System.out.println("Tiger hunting"); } } public class Snake extends Animal implements hunt{ @Override public void drink(){ System.out.println("Snake drink"); hunting(); } @Override public void hunting() { System.out.println("Snake hunting"); } } public class Farmer { public void feedWatch(Animal A){ System.out.println("农民给" + A + "喂水"); A.drink(); } } public class Demo1 { public static void main(String[] args) { Farmer f1 = new Farmer(); tiger t1 = new tiger(); sleep s1 = new sleep(); Snake s2 = new Snake(); f1.feedWatch(t1); f1.feedWatch(s1); f1.feedWatch(s2); } }
四、利用接口来补充多继承继承缺失
接口中的类没有实现,可以用类来实现多个接口。
Java中的类是单继承,但是接口是多继承。
例如:有swim、run两个接口,我们创建一个Dog类来实现这两个接口的方法
public interface swim { void swim(); } public interface run { void run(); } //一个Dog类可以拥有两种能力,swim和run,只需要实现两个接口即可,必须重写这两个接口所有抽象方法 public class Dog implements swim,run{ @Override public void run() { } @Override public void swim() { } }
五、接口的继承
接口可以继承其他接口且可继承多个。
一个接口不能继承一个抽象类,但是却可以通过extends关键字同时继承多个接口,实现接口的多继承。
例题:当有A、B两个接口,且A、B接口中有相同的属性name,那么当C类继承A、B接口时,能否使用C.name调用父类接口name?
不能,因为用C.name存在二义性,并不知道此时调用的是A接口的还是B接口的name,所以我们只能用A.name或B.name来访问父类的静态变量的常量。
接口多态案例
不同引用类型,仅可调用自身类型中声明的方法。
public interface swim { void swim(); } public interface run { void run(); } //一个类可以实现多个接口 public class Dog implements swim, run { @Override public void run() { } @Override public void swim() { } } public class Demo { public static void main(String[] args) { run dog1 = new Dog(); swim dog2 = new Dog(); Dog dog3 = new Dog(); //其中dog1只能调用run方法,dog2只能调用swim方法,而dog3可以调用两个方法 dog1.run(); dog2.swim(); dog3.run(); dog3.swim(); } }
六、常量接口
在项目中往往需要很多常量使用,而在接口中定义常量默认为常量,所以接口用来定义常量非常合适。在项目中用来定义常量的接口称为常量接口,里面可能没有任何方法。
//常量名全大写 public interface Finalable { // 例如当项目中需要经常往一个网站上传东西,可以用常量来存储网站路径 String UPLOAD_URL = "www.baidu.com"; // 例如网页中经常使用的一张图片,图片路径可以用常量存储 String IMAGES_PATH = "D:/images"; }
七、接口在新版的改变(jdk 1.8)
7.1 接口中使用静态方法
因为静态方法不能被重写,且调用时用类名调用。
public interface run { void run(); //接口中的静态方法 private void s1(){ } }
7.2 默认方法
用default修饰的方法为默认方法,修饰后可以给方法写方法体。
public interface run { //接口中的默认方法 default void s1(){ //方法体 } }
八、接口回调
先有接口使用者,再有接口实现者。
简单来说接口回调就是:调用者A类访问了被调用者B类中的m1方法.这个m1方法在执行完毕后又调用了A类中的其他方法.
问:我们需要解决m1方法是如何返回调用A类的其他方法的?
答:例如老师给学生布置作业,作业布置后学生写作业,写完后学生将作业给老师再批改,给老师批改属于接口回调。代码如下:
public class Demo1 { public static void main(String[] args) { Teacher t1 = new Teacher(); Student s1 = new Student(); //老师给s1学生布置作业 t1.Homework(s1); //老师布置作业!!! //学生做作业ing //学生做完了ed //老师批改作业ing。。。。 } } //因为批改作业的能力不只有老师会,家长也会批改,所以我们将批改作业设置为接口 public interface Correct { void correct(); } public class Teacher implements Correct{ //老师布置作业 public void Homework(Student s1){ System.out.println("老师布置作业!!!"); //布置作业后学生写作业,并告诉他写完让老师批改,this表示当前对象 s1.dohomework(this); } @Override public void correct() { System.out.println("老师批改作业ing。。。。"); } } public class Student { //这里接收批改作业的对象,传过来的对象为一个内存地址 public void dohomework(Correct c1){ //System.out.println(c1); System.out.println("学生做作业ing"); System.out.println("学生做完了ed"); //做完作业后告诉老师自己做完作业,让老师批改 c1.correct(); } }