目录
接口的基本介绍
接口的注意事项和使用细节
接口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接口,所以就需要将接口中的方法全部实现
@Override
public 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,Co
9)接口的修饰符 只能是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继承类
接口和继承解决的问题不同
继承的价值主要在于:解决代码的复用性和可维护性。
接口的价值主要在于:设计,设计好各种规范(方法),让其它类去实现这些方法。即更加的灵活..
接口比继承更加灵活
接口比继承更加灵活,继承是满足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);
}
@Override
public void swimming() {
System.out.println(getName() + " 可以游泳");
}
@Override
public 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("猫在吃鱼");
}
@Override
public void say() {
}
}
class pig implements Animal {
public void eat() {
System.out.println("猪在睡觉");
}
@Override
public 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 {
@Override
public 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();//ok
System.out.println(b.a); //23
System.out.println(A1.a); //23
System.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.x
2.使用接口名.属性名 访问的就是接口中的属性 使用super.属性名 访问的就是父类中的属性
*/
//System.out.println(x); //错误,原因不明确x
System.out.println(A.x + " " + super.x);
}
}