目录
在现实生活中,接口的例子比比皆是,比如:电源插座,主机上的USB接口等。这些插口中可以插所有符合规范的设备。通过这个例子我们知道,接口就是公共的行为规范标准,大家在实现时,只要符合规范标准,就可以通用。在java中,接口可以看成是:多个类的公共规范,是一种引用数据类型。
语法规则
通过关键字interface来定义一个接口。在创建接口时,接口的命名一般以大写字母I开头。
接口中的成员默认都是public static final的,接口中的成员方法默认都是public abstract的,所以一般都不写,保持代码简洁性。
interface IShape {
//public static final int a = 10;
int a = 0;
//public abstract void draw();
void draw();
}
在接口中,不可以有普通成员方法
java8开始,允许在接口当中定义一个default方法,这个方法可以有具体的实现
interface IShape {
int a = 0;
void draw();
default public void test() {
System.out.println("test()");
}
}
接口当中的方法,如果是static修饰的方法,那么可以有具体的实现
public static void test2() {
System.out.println("static方法");
}
接口当中不能有构造方法和代码块
接口不可以通过new关键字进行实例化
类和接口之间可以通过关键字implements来实现接口,且类中要重写接口中的抽象方法
class Rect implements IShape {
@Override
public void draw() {
System.out.println("矩形");
}
}
当一个类实现接口当中的方法之后,当前类中的方法不能不加public
接口可以发生向上转型,也可以发生动态绑定
public class Test8_4 {
public static void drawMap(IShape iShape) {
iShape.draw();
}
public static void main(String[] args) {
IShape iShape = new Rect();
drawMap(iShape);
drawMap(new Flower());
}
}
输出结果:
一个接口也会产生独立的字节码文件
例子
我们来看一个具体的例子:
新建一个名为IUSB的接口
public interface IUSB {
void openDevice();//打开服务
void closeDevice();//关闭服务
}
新建一个类Mouse,通过implements实现IUSB
public class Mouse implements IUSB{
@Override
public void openDevice() {
System.out.println("打开鼠标");
}
@Override
public void closeDevice() {
System.out.println("关闭鼠标");
}
public void click() {
System.out.println("点击鼠标");
}
}
新建一个类keyBoard类,通过implements实现IUSB
public class keyBoard implements IUSB{
@Override
public void openDevice() {
System.out.println("打开键盘");
}
@Override
public void closeDevice() {
System.out.println("关闭键盘");
}
public void inPut() {
System.out.println("输入");
}
}
新建一个Computer类,类中分别有三个方法,分别是打开电脑、关闭电脑、使用服务
public class Computer {
public void powerOn() {
System.out.println("打开笔记本电脑");
}
public void powerOff() {
System.out.println("关闭笔记本电脑");
}
public void useDevice(IUSB iusb) {
//启动服务
iusb.openDevice();
if (iusb instanceof Mouse) {
//如果是鼠标调用 那么将iusb强转成Mouse类并调用click方法
Mouse mouse = (Mouse) iusb;
mouse.click();
} else if (iusb instanceof keyBoard) {
//如果是键盘调用 那么将iusb强转成keyBoard类并调用inPut方法
keyBoard keyBoard = (demo4.keyBoard) iusb;
keyBoard.inPut();
}
//关闭服务
iusb.closeDevice();
}
}
下面我们来测试一下useDevice方法
public static void main(String[] args) {
Computer computer = new Computer();
computer.powerOn();//打开电脑
computer.useDevice(new Mouse());//鼠标
computer.useDevice(new keyBoard());//键盘
computer.powerOff();//关闭电脑
}
你可以自己分析一下程序的输出结果是什么。
这里我直接给出运行结果:
实现多个接口
在java中,类和类之间是单继承的,一个类只能有一个父类,不支持多继承,但是一个类可以实现多个接口。我们认识了很多动物,有会飞的,会跑的,会游的,现在我们写一个代码来实现它。
新建一个IFlying接口
public interface IFlying {
void fly();
}
新建一个ISwimming接口
public interface ISwimming {
void swim();
}
新建一个IRunning接口
public interface IRunning {
void run();
}
新建一个Animal类,这是一个抽象类
public abstract class Animal {
public String name;
public int age;
public abstract void eat();
//构造方法
public Animal(String name,int age) {
this.name = name;
this.age = age;
}
}
新建一个Dog类,继承Animal,并重写Animal中的抽象方法
public class Dog extends Animal{
@Override
public void eat() {
System.out.println(this.name+"吃狗粮");
}
//构造方法
public Dog(String name,int age) {
super(name, age);
}
}
对于狗来说,他会狗刨(游泳),会跑,他的功能不止一个,通过implements实现IRunning和ISwimming,并重写接口中的方法
public class Dog extends Animal implements IRunning,ISwimming{
@Override
public void eat() {
System.out.println(this.name+"吃狗粮");
}
//构造方法
public Dog(String name,int age) {
super(name, age);
}
@Override
public void run() {
System.out.println(this.name+"用狗腿跑");
}
@Override
public void swim() {
System.out.println(this.name+"正在狗刨");
}
}
【注】一定是先继承,再实现;在java中只能继承一个类,实现多个接口。
新建一个Bird类,继承Animal,实现IRunning,IFlying接口
public class Bird extends Animal implements IFlying,IRunning{
@Override
public void eat() {
System.out.println(this.name+"吃鸟食");
}
public Bird(String name,int age) {
super(name, age);
}
@Override
public void run() {
System.out.println(this.name+"用鸟腿跑");
}
@Override
public void fly() {
System.out.println(this.name+"正在飞");
}
}
新建一个测试类Test10_1
public class Test10_1 {
public static void test1(Animal animal) {
animal.eat();
}
public static void test2(IRunning iRunning) {
iRunning.run();
}
public static void test3(ISwimming iSwimming) {
iSwimming.swim();
}
public static void test4(IFlying iFlying) {
iFlying.fly();
}
public static void main(String[] args) {
Dog dog = new Dog("小狗",2);
Bird bird = new Bird("小鸟",1);
test1(bird);
test1(dog);
System.out.println("==========================");
//dog和bird都实现了IRunning
test2(bird);
test2(dog);
System.out.println("==========================");
//只有dog实现了ISwimming
test3(dog);
System.out.println("==========================");
//只有bird实现了IFlying
test4(bird);
System.out.println("==========================");
}
}
你可以自己分析一下输出结果是什么。
这里我直接给出结果:
现在我们再新建一个Robot类,它不属于动物,但有跑的功能
public class Robot implements IRunning{
@Override
public void run() {
System.out.println("机器人在跑");
}
}
public static void main(String[] args) {
test2(new Robot());
}
输出结果为:
只有具备功能即可,十分灵活。
通过上面这个例子,我们知道,继承表达的是is-a的语义,而接口表达的是具有xxx特性。
接口之间的继承
现在我们定义三个接口A、B、C
interface A {
void testA();
}
interface B {
void testB();
}
interface C {
void testC();
}
现有一个接口具备B和C接口的功能,难道要再新建一个接口D,把B、C的功能放进去吗?
interface D {
void testB();
void testC();
}
这样写不太合适,不能解决长久的问题,我们可以用关键字extends,此时extends意为拓展
interface D extends B,C{
//D这个接口具备了B和C的功能,同时D可以也定义属于自己的功能
void testD();
}
那么当一个类实现D接口时,要重写B、C、D的方法
public class Test10_2 implements D{
@Override
public void testB() {
System.out.println("B");
}
@Override
public void testC() {
System.out.println("C");
}
@Override
public void testD() {
System.out.println("D");
}
}
接口间的继承相当于把多个接口合并在一起。
抽象类和接口的区别
区别 | 抽象类(abstract) | 接口(interface) |
结构组成 | 普通类+抽象方法 | 抽象方法+全局常量 |
权限 | 各种权限 | public |
子类使用 | 使用extends关键字继承抽象类 | 使用implements关键字实现接口 |
关系 | 一个抽象类可以实现若干接口 | 接口不能继承抽象类,但是接口可以使用extends关键字继承多个父接口 |
子类权限 | 一个子类只能继承一个抽象类 | 一个子类可以实现多个接口 |