目录
接口的基本介绍
接口的注意事项和使用细节
接口vs继承
接口体现多态
接口体现多态数组
接口体现多态传递现象
接口的习题
第一题
第二题
接口的基本介绍
接口就是给出一些没有实现的方法,封装到一起,到某个类要使用的时候,在根据具体情况把这些方法写出来。
语法:
interface 接口名{
//属性
//方法(1.抽象方法2默认实现方法3.静态方法)
}
class 类名 implements 接口 { 自己属性; 自己方法; 必须实现的接口的抽象方法
}
小结 1.在Jdk7.0前 接口里的所有方法都没有方法体,即都是抽象方法。 2.Jdk8.0后接口可以有静态方法,默认方法,也就是说接口中可以有方法的具体实现
代码演示:
注意:在jdk8后,可以有默认实现方法,需要使用default关键字修饰,接口中的方法默认都是抽象方法也就是说,方法不能有具体的实现,如果想要实现方法,那么需要使用default修饰,且jdk版本要在8后
package idea.chapter10.Interface;/*** 演示接口的基本使用*/
public class interface01 {public static void main(String[] args) {/*接口就是给出一些没有实现的方法,封装到一起,到某个类要使用的时候,在根据具体情况把这些方法写出来。语法:interface 接口名{//属性//方法(1.抽象方法2默认实现方法3.静态方法)}class 类名 implements 接口 { 自己属性; 自己方法; 必须实现的接口的抽象方法}小结 1.在Jdk7.0前 接口里的所有方法都没有方法体,即都是抽象方法。 2.Jdk8.0后接口可以有静态方法,默认方法,也就是说接口中可以有方法的具体实现*/}
}interface AA {//可以有属性还有方法//属性public int n1 = 10;//方法//在接口中,抽象方法,可以省略abstract关键字public void hi();//小结
//1.在Jdk7.0前 接口里的所有方法都没有方法体,即都是抽象方法。
//2.Jdk8.0后接口可以有静态方法,默认方法,也就是说接口中可以有方法的具体实现//在jdk8后,可以有默认实现方法,需要使用default关键字修饰default public void ok() {System.out.println("ok ...");}//在jdk8后, 可以有静态方法public static void cry() {System.out.println("cry ....");}
}
接口的注意事项和使用细节
1)接口不能被实例化
2)接口中所有的方法是 public方法,接口中抽象方法,可以不用abstract修饰 图示: void aaa(); 实际上是 abstract void aa0; void aaa()
3)一个普通类实现接口,就必须将该接口的所有方法都实现。
4)抽象类实现接口,可以不用实现接口的方法。
代码演示:
package idea.chapter10.Interface;/*** 演示接口的注意实现和使用细节*/
public class InterfaceDetail01 {public static void main(String[] args) {/*结论1)接口不能被实例化2)接口中所有的方法是 public方法,接口中抽象方法,可以不用abstract修饰 图示: void aaa(); 实际上是 abstract void aa0; void aaa()3)一个普通类实现接口,就必须将该接口的所有方法都实现。4)抽象类实现接口,可以不用实现接口的方法。*///1)接口不能被实例化//这是错误的,接口不能实例化//B b = new B();}
}//定义了一个接口
interface B {//2)接口中所有的方法是 public方法,接口中抽象方法,可以不用abstract修饰 图示: void aaa(); 实际上是 abstract void aa0; void aaa()//这是错误的,接口中的方法都是public方法,//protected void hi(){};//因为接口的方法都是public和abstract的,因此这样写等价于 abstract public void aaa();void aaa();//等价于 abstract public void aaa();
}//一个普通类实现接口,就必须将该接口的所有方法都实现。
class C implements B {//因为我们C类实现了B接口,所以就需要将接口中的方法全部实现@Overridepublic void aaa() {}
}//抽象类实现接口,可以不用实现接口的方法。
abstract class A implements B {
//因为A类是抽象类,所以去实现B接口,就不用实现接口中的方法
}
5)一个类同时可以实现多个接口
6)接口中的属性,只能是final的,而且是public static final修饰符。比如:int a=1;实际上是 public static final int a=1;(必须初始化)
7)接口中属性的访问形式:接口名.属性名
8)接口不能继承其它的类,但是可以继承多个别的接口[举例]
interface A extends B,Co
9)接口的修饰符 只能是public和默认,这点和类的修饰符是一样的。
代码演示:
注意:因为接口中的属性只能是是final ,并且是public static final 修饰的,因此我们看到的是 int n1 = 1;实际上是 public static final int n1 = 1; 注意接口中的属性必须初始化,因为final修饰的属性,必须初始化,这也是为什么在接口中的属性,一定要初始化的原因
package idea.chapter10.Interface;/*** 演示接口的注意实现和使用细节2*/
public class InterfaceDetail02 {public static void main(String[] args) {/*结论5)一个类同时可以实现多个接口6)接口中的属性,只能是final的,而且是public static final修饰符。比如:int a=1;实际上是 public static final int a=1;(必须初始化)7)接口中属性的访问形式:接口名.属性名8)接口不能继承其它的类,但是可以继承多个别的接口[举例]interface A extends B,Co9)接口的修饰符 只能是public和默认,这点和类的修饰符是一样的。*///接口中属性的访问形式:接口名.属性名System.out.println(AAA.n1);}
}//接口不能继承其它的类,但是可以继承多个别的接口[举例]
//此时我们的AAA接口就继承了BBB接口,和CCC接口
interface AAA extends BBB, CCC {//接口中的属性,只能是final的,而且是public static final修饰符。比如:int a=1;实际上是 public static final int a=1;(必须初始化)//因为接口中的属性只能是是final ,并且是public static final 修饰的,因此我们看到的是 int n1 = 1;实际上是 public static final int n1 = 1;//注意必须初始化,因为final修饰的属性,必须初始化,这也是为什么在接口中的属性,一定要初始化的原因int n1 = 1;//实际上是 public static final int n1 = 1;}interface BBB {int a = 10;
}interface CCC {}//接口的修饰符 只能是public和默认,这点和类的修饰符是一样的。
//这样是错误的,接口不能使用private修饰 ,只能是public和默认的
//private interface DDD{
//
//}//一个类同时可以实现多个接口,此时我们的Dog类就实现了AAA和BBB两个接口
class Dog implements AAA, BBB {}
接口vs继承
实现接口vs继承类
接口和继承解决的问题不同
继承的价值主要在于:解决代码的复用性和可维护性。
接口的价值主要在于:设计,设计好各种规范(方法),让其它类去实现这些方法。即更加的灵活..
接口比继承更加灵活
接口比继承更加灵活,继承是满足is- a的关系,而接口只需满足like- a的关系;
思路分析:
1.我们发现,当我们继承完Monkey类中,想要继续实现其他方法,就很难了,因为Java是单继承机制,因此我们可以通过实现接口的方法来完成 。我们的猴子本来只会爬树,但是在我们继承接口后,或者可以游泳,也可以飞翔
小结:
当子类继承了父类,就自动的拥有父类的功能
如果子类需要扩展功能,可以通过实现接口的方式扩展.
可以理解 实现接口 是 对java 单继承机制的一种补充.
package idea.chapter10.Interface;/*** 演示继承和接口的区别*/
public class ExtendsVsInterface {public static void main(String[] args) {LittleMonkey wuKong = new LittleMonkey("猴子");wuKong.climbing();wuKong.swimming();wuKong.flying();}
}//定义了一个猴子类
class Monkey {private String name;public Monkey(String name) {this.name = name;}public void climbing() {System.out.println(name + " 会爬树");}public String getName() {return name;}public void setName(String name) {this.name = name;}
}//定一个鱼的接口
interface Fish {void swimming();
}//定一个鸟的接口
interface Bird {void flying();
}//继承
//小结: 当子类继承了父类,就自动的拥有父类的功能
// 如果子类需要扩展功能,可以通过实现接口的方式扩展.
// 可以理解 实现接口 是 对java 单继承机制的一种补充.//我们发现,当我们继承完Monkey类中,想要继续实现其他方法,就很难了,因为Java是单继承机制,因此我们可以通过实现接口的方法来完成
//我们的猴子本来只会爬树,但是在我们继承接口后,或者可以游泳,也可以飞翔
class LittleMonkey extends Monkey implements Fish, Bird {public LittleMonkey(String name) {super(name);}@Overridepublic void swimming() {System.out.println(getName() + " 可以游泳");}@Overridepublic void flying() {System.out.println(getName() + " 可以飞翔");}
}
接口体现多态
代码演示:
package idea.chapter10.Interface;/*** 演示接口体现多态*/
public class InterfacePolyParameter {public static void main(String[] args) {//接口体现多态//接口可以指向,实现了该接口类的对象实例IF if01 = new Monster();if01 = new Car();IF if02 = new Car();//继承体现多态Animal animal = new Cat();//向上转型animal = new Cat();Animal animal1 = new pig();}
}//定义了一个接口
interface IF {
}//定义了两个类,实现了IF接口
class Monster implements IF {
}class Car implements IF {
}//继承体现多态
class Animal {
}class pig extends Animal {
}class Cat extends Animal {
}
接口体现多态数组
思路分析: 1.因为接口也可以体现多态,所以我们的Animal接口可以指向,实现了Animal接口的对象实例,所以我们的Animal类型的数组可以存放Cat类和pig类2.因为在Animal类中有抽象方法,所以我们的类在实现接口后就必须实现该方法3.我们在遍历数组的过程中,判断当前数组的运行类型是什么,使用 instanceof 关键字,判断的是运行类型,和我们之前的多态数组一样,如果是当前类型的子类型或者就是当前类型,那么我们就向下转型,即使Cat类中和pig类中的方法名都一样都是eat方法但是,有动态绑定机制,会找到对应类中的eat方法
package idea.chapter10.Interface;/*** 接口体现多态数组*/
public class InterfacePolyArray {public static void main(String[] args) {//创建一个Animal数组Animal[] animal = new Animal[2];animal[0] = new Cat();animal[1] = new pig();/*思路分析:1.因为接口也可以体现多态,所以我们的Animal接口可以指向,实现了Animal接口的对象实例,所以我们的Animal类型的数组可以存放Cat类和pig类2.因为在Animal类中有抽象方法,所以我们的类在实现接口后就必须实现该方法3.我们在遍历数组的过程中,判断当前数组的运行类型是什么,使用 instanceof 关键字,判断的是运行类型,和我们之前的多态数组一样,如果是当前类型的子类型或者就是当前类型,那么我们就向下转型,即使Cat类中和pig类中的方法名都一样都是eat方法但是,有动态绑定机制,会找到对应类中的eat方法*/for (int i = 0; i < animal.length; i++) {if (animal[i] instanceof Cat) {((Cat) animal[i]).eat();} else if (animal[i] instanceof pig) {((pig) animal[i]).eat();} else {System.out.println("不做处理");}}}
}interface Animal {void say();}class Cat implements Animal {public void eat() {System.out.println("猫在吃鱼");}@Overridepublic void say() {}
}class pig implements Animal {public void eat() {System.out.println("猪在睡觉");}@Overridepublic void say() {}
}
接口体现多态传递现象
思路分析:
因为IG 继承了 IH 接口,而Teacher 类实现了 IG接口
那么,实际上就相当于 Teacher 类也实现了 IH接口.
这就是 接口多态传递现象.
package idea.chapter10.Interface;/*** 演示接口体现多态传递*/
public class InterfacePolyPass {public static void main(String[] args) {//接口类型的变量可以指向,实现了该接口的类的对象实例IG ig = new Teacher();//因为IG 继承了 IH 接口,而Teacher 类实现了 IG接口//那么,实际上就相当于 Teacher 类也实现了 IH接口.//这就是 接口多态传递现象.IH ih = new Teacher();}
}interface IH {void hi();
}interface IG extends IH {
}class Teacher implements IG {@Overridepublic void hi() {}
}
接口的习题
第一题
思路分析: 1.我们要注意到接口中的属性都是 public static final修饰的 2.因为B1类实现了A1接口,所以b可以访问a 3.A1.a因为a是static的并且A1是接口所以可以直接访问 4.B1.a因为B1实现了A1接口,所以可以使用A1中的属性
package idea.chapter10.Interface;public class InterfaceExercise01 {public static void main(String[] args) {B1 b = new B1();//okSystem.out.println(b.a); //23System.out.println(A1.a); //23System.out.println(B1.a); //23}
}/*
思路分析:
1.我们要注意到接口中的属性都是 public static final修饰的
2.因为B1类实现了A1接口,所以b可以访问a
3.A1.a因为a是static的并且A1是接口所以可以直接访问
4.B1.a因为B1实现了A1接口,所以可以使用A1中的属性*/
interface A1 {int a = 23; //等价 public static final int a = 23;
}class B1 implements A1 {//正确
}
第二题
思路分析: 1.因为C类继承了B 并且实现了A 所以在直接使用x属性时候,会发现在B类中有x属性,在接口A中也有x属性,因此会报错,可以明确的指定x访问接口的 x 就使用 A.x访问父类的 x 就使用 super.x 2.使用接口名.属性名 访问的就是接口中的属性 使用super.属性名 访问的就是父类中的属性
package idea.chapter10.Interface;public class InterfaceExercise02 {public static void main(String[] args) {new C().pX();}
}interface A { // 1min 看看int x = 0;
} //想到 等价 public static final int x = 0;class B {int x = 1;
} //普通属性class C extends B implements A {public void pX() {/*思路分析:1.因为C类继承了B 并且实现了A 所以在直接使用x属性时候,会发现在B类中有x属性,在接口A中也有x属性,因此会报错,可以明确的指定x访问接口的 x 就使用 A.x访问父类的 x 就使用 super.x2.使用接口名.属性名 访问的就是接口中的属性 使用super.属性名 访问的就是父类中的属性 *///System.out.println(x); //错误,原因不明确xSystem.out.println(A.x + " " + super.x);}}