接口
一、接口的语法
语法:
public interface 接口名{
// 属性(所有的属性均为静态常量)
// 方法(所有的方法均为抽象方法)
}
注意:接口没有构造方法,也不能创建对象。
public interface MyInterface {
int COUNT = 10; // 属性默认是public static final
void m1(); // 方法默认是public abstract
}
二、与抽象类的异同
相同点:
- 都不能直接创建对象
- 都可以定义抽象方法
不同点:
- 抽象类可以定义构造方法、代码块,而接口不能定义
- 抽象类可以定义实例属性,静态属性,实例方法,静态方法;而接口只能定义静态常量,抽象方法、jdk8后可以定义静态方法。
三、接口的概念
是一种能力和约定,接口代表能力,方法代表约定。
主要是为了解决Java中多继承的问题,而又不会出现c++中多继承相关的问题。因为接口中的方法没有实现,即使从多个接口继承过来相同的方法也不会产生任何问题。
四、基本使用
public interface USB {
void use();
}
public class Fan implements USB{
@Override
public void use() {
System.out.println("usb风扇被使用");
}
}
public class KeyBoard implements USB{
@Override
public void use() {
System.out.println("usb键盘被使用");
}
}
public class TestMain {
public static void main(String[] args) {
USB u1 = new Fan();
u1.use();
USB u2 = new KeyBoard();
u2.use();
}
}
五、接口的多态
接口的使用场景:需要具备某种能力,但是又没有相应的父子关系存在时,就应该使用接口。
例如:
电脑上有USB接口,只要具备有使用USB能力的设备都可以连接,USB风扇、键盘、鼠标、手机等,它们很难找到父子关系,从而抽象出父类,此时应该使用接口。
要举办一次飞行表演,可以使用鸽子、飞机、气球、天使等来进行飞行表演,此时也无法找到或者抽象出相应的父类,应该使用接口,只要具备有飞行能力即可。
// USB接口的案例
public interface USB {
void use();
}
public class Fan implements USB{
@Override
public void use() {
System.out.println("usb风扇被使用");
}
}
public class KeyBoard implements USB{
@Override
public void use() {
System.out.println("usb键盘被使用");
}
}
public class Computer {
public void operate(USB usb) {
System.out.println("正在使用电脑上的usb接口");
usb.use();
}
}
public class TestMain {
public static void main(String[] args) {
USB u1 = new Fan();
USB u2 = new KeyBoard();
Computer computer = new Computer();
computer.operate(u2);
}
}
// 飞行表演的案例
// 涉及到的接口为飞行接口(Flyable、fly())、鸽子(Bird)、飞机(Plane)、天使(Angel)
// 应用场景的类:节日(Day、表演show(飞行接口))
/**
* 飞行能力
*/
public interface Flyable {
void fly();
}
public class Bird implements Flyable{
@Override
public void fly() {
System.out.println("鸽子正在飞行表演...");
}
}
public class Angel implements Flyable {
@Override
public void fly() {
System.out.println("天使正在进行飞行表演...");
}
}
public class Plane implements Flyable {
@Override
public void fly() {
System.out.println("飞机正在进行飞行表演...");
}
}
/**
* 节日
*/
public class Day {
/**
* 表演
*/
public void show(Flyable flyable) {
System.out.println("表演开始。。。");
flyable.fly();
}
}
public class TestMain {
public static void main(String[] args) {
Day day = new Day();
Flyable flyable = new Angel();
day.show(flyable);
}
}
六、同时继承类并实现接口
/**
* 动物类作为父类
*/
public abstract class Animal {
public abstract void eat();
}
public interface Swimmable {
void swim();
}
public interface Runnable {
void run();
}
// 同时实现多个接口,使用逗号隔开
// 继承类同时又实现接口,需要将继承放到前面
public class Dog extends Animal implements Runnable, Swimmable{
@Override
public void eat() {
System.out.println("狗正在吃骨头...");
}
@Override
public void swim() {
System.out.println("狗正在游泳");
}
@Override
public void run() {
System.out.println("狗正在跑...");
}
}
public class TestMain {
public static void main(String[] args) {
// 当创建子类对象时,可以调用该类中所有的方法(继承自父类或实现接口)
Dog dog = new Dog();
dog.eat();
dog.run();
dog.swim();
// 当使用父类引用指向子类对象时,只能调用父类的方法,要调用其他的方法,需要向下转型
Animal animal = new Dog();
animal.eat();
// 当使用接口来引用实现类的对象时,也只能调用该接口中声明的方法,要调用其他的方法,需要向下转型
Runnable runnable = new Dog();
runnable.run();
Swimmable swimmable = new Dog();
swimmable.swim();
}
}
七、常见关系
类与类:
- 单继承,使用extends关键字
类与接口:
- 多实现,implements 接口1, 接口2, 接口3
接口与接口:
- 多继承,extends 接口1, 接口2
public interface A {
void a();
}
public interface B {
void b();
}
public interface C extends A, B{
void c();
}
public class MyClass implements C{
@Override
public void a() {
}
@Override
public void b() {
}
@Override
public void c() {
}
}
八、常量接口
一种特殊的接口,在里面定义项目中需要的常量,不定义任何方法。
因为在接口中定义的变量默认是常量,比类更适合于定义常量。
public interface Constants {
int PAGE_SIZE = 10;
String MESSAGE_TYPE = "1";
}
九、默认方法和静态方法(了解)
在jdk8的新版本中,添加了默认方法和静态方法。
静态方法需要类名调用,但是默认方法,需要创建实现类的对象才能调用。
- 如果一个类实现了多个接口,在多个接口中都有相同的静态属性或静态方法,不会报错,在使用时应该使用接口名去调用相应的静态属性或静态方法。
- 如果一个类实现了多个接口,在多个接口中有相同默认方法,会报错,要求必须在实现类中重写该方法。如果在重写时,需要调用父接口中的默认方法,需要使用接口名.super.方法的方式。
public interface A {
int COUNT = 5;
public static void m2() {
System.out.println("A接口中的静态m2方法");
}
default void m1() {
System.out.println("A接口中的m1方法");
}
}
public interface B {
int COUNT = 10;
default void m1() {
System.out.println("B接口中的m1方法");
}
public static void m2() {
System.out.println("B接口中的静态m2方法");
}
}
public class AClass implements A, B{
@Override
public void m1() {
A.super.m1(); // 调用A作为父接口中的m1方法
B.super.m1();
System.out.println("AClass中的m1方法");
}
}
public class TestMain {
public static void main(String[] args) {
A a = new AClass();
a.m1();
// 使用接口名去调用相应的静态属性或静态方法
A.m2();
B.m2();
System.out.println(A.COUNT);
System.out.println(B.COUNT);
}
}
十、接口回调
回调字面意思是回头调用。
例如:
老师布置作业。
学生完成作业。
学生提交作业。
老师批改作业。
public interface Callback {
void pigai();
}
public class Teacher implements Callback{
private Student student;
public Teacher(Student student) {
super();
this.student = student;
}
public void buzhi() {
System.out.println("老师布置作业");
student.wancheng(this);
}
@Override
public void pigai() {
System.out.println("老师批改作业");
}
}
public class Student {
public void wancheng(Callback callback) {
System.out.println("学生完成作业...");
System.out.println("学生提交作业...");
callback.pigai();
}
}
public class TestMain {
public static void main(String[] args) {
Student student = new Student();
Teacher teacher = new Teacher(student);
teacher.buzhi();
}
}
可以再创建一个家长也参与布置作业和批改作业。
public class Parent implements Callback{
private Student student;
public Parent(Student student) {
super();
this.student = student;
}
public void buzhi() {
System.out.println("家长布置作业");
student.wancheng(this);
}
@Override
public void pigai() {
System.out.println("家长批改作业");
}
}
public class TestMain {
public static void main(String[] args) {
Student student = new Student();
Parent parent = new Parent(student);
parent.buzhi();
}
}