java接口的使用(二)

本文介绍了接口的多实现,包括使用接口的注意事项、实战示例。阐述了接口中的多态性,即父类引用指向子类对象,说明了多态中成员变量和方法的访问规则。还讲解了对象的向上、向下转型,以及如何判断父类引用对象的子类类型。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在继承体系中,一个类只能继承一个父类。而对于接口而言,一个类是可以实现多个接口的,这叫做接口的多实现。并且,一个类能继承一个父类,同时实现多个接口。
注意事项:
使用接口的时候,需要注意:

  1. 接口是没有静态代码块或者构造方法的。
  2. 一个类的直接父类是唯一的,但是一个类可以同时实现多个接口。
    格式:
    public class MyInterfaceImpl implements MyInterfaceA, MyInterfaceB {
    // 覆盖重写所有抽象方法
    }
  3. 如果实现类所实现的多个接口当中,存在重复的抽象方法,那么只需要覆盖重写一次即可。
  4. 如果实现类没有覆盖重写所有接口当中的所有抽象方法,那么实现类就必须是一个抽象类。
  5. 如果实现类实现的多个接口当中,存在重复的默认方法,那么实现类一定要对冲突的默认方法进行覆盖重写。
  6. 一个类如果直接父类当中的方法,和接口当中的默认方法产生了冲突,优先用父类当中的方法。

实战:
接口A

package cn.itcast.day10.demo02;

public interface MyInterfaceA {

    // 错误写法!接口中不能有静态代码块
//    static{
//
//    }

    // 错误写法!接口中不能有构造方法
//    public MyInterfaceA(){}


    public abstract void methodA();

    public abstract void methodAbs();

    public default void methodDefault(){
        System.out.println("默认方法AAA");
    }

}

接口B

package cn.itcast.day10.demo02;

public interface MyInterfaceB {

    // 错误写法!接口不能有静态代码块
//    static {
//
//    }

    // 错误写法!接口不能有构造方法
//    public MyInterfaceA(){
//
//    }

    public abstract void methodB();

    public abstract void methodAbs();

    public default void methodDefault(){
        System.out.println("默认方法BBB");
    }
}

实现类实现接口A,B; 没有覆盖重写接口A,B中所有的抽象方法,因此该类必须是抽象类

package cn.itcast.day10.demo02;

public abstract class MyInterfaceAbstract implements MyInterfaceA, MyInterfaceB{
    @Override
    public void methodA() {

    }

//    @Override
//    public void methodB() {
//
//    }

    @Override
    public void methodAbs() {

    }

    @Override
    public void methodDefault(){

    }
}

实现类覆盖重写了A,B接口中的所有抽象方法,并对冲突的默认方法进行了覆盖重写

package cn.itcast.day10.demo02;

public class MyInterfaceImpl /*extends Object*/ implements MyInterfaceA, MyInterfaceB{


    @Override
    public void methodA() {
        System.out.println("覆盖重写了A方法");

    }

    @Override
    public void methodB() {
        System.out.println("覆盖重写了B方法");
    }

    @Override
    public void methodAbs() {
        System.out.println("覆盖重写了AB接口中都有的抽象方法");

    }

    @Override
    public void methodDefault(){
        System.out.println("对多个接口当中冲突的默认方法进行覆盖重写");
    }
}

一个类如果直接父类当中的方法,和接口当中的默认方法产生了冲突,优先用父类当中的方法。
父类:

package cn.itcast.day10.demo02;

public class Fu {

    public void method(){
        System.out.println("父类方法");
    }
}

接口:

package cn.itcast.day10.demo02;

public interface MyInterface {

    public default void method(){
        System.out.println("接口的默认方法");
    }
}

实现类,继承父类方法并且实现接口

package cn.itcast.day10.demo02;

public class Demo01Interface {

    public static void main(String[] args) {

        Zi zi = new Zi();

        zi.method();
    }
}

结果如下所示:
在这里插入图片描述

  1. 类与类之间是单继承的。直接父类只有一个。
  2. 类与接口之间是多实现的。一个类可以实现多个接口。
    3. 接口与接口之间是多继承的。

注意事项:

  1. 多个父接口当中的抽象方法如果重复,没关系。
    2. 多个父接口当中的默认方法如果重复,那么子接口必须进行默认方法的覆盖重写,【而且带着default关键字】。

父类接口A

package cn.itcast.day10.demo03;

public interface MyInterfaceA {

    public abstract void methodA();

    public abstract void methodCommon();

    public default void methodDefault(){
        System.out.println("AAA");
    }
}

父类接口B

package cn.itcast.day10.demo03;

public interface MyInterfaceB {

    public abstract void methodB();
    public abstract void methodCommon();

    public default void methodDefault(){
        System.out.println("BBB");
    }
}

子接口继承接口A,B

package cn.itcast.day10.demo03;

public interface MyInterface extends MyInterfaceA, MyInterfaceB{
    public abstract void method();

    @Override
    public default void methodDefault(){

    }

}

接口中的多态性

代码当中体现多态性,其实就是一句话:父类引用指向子类对象。
格式:
父类名称 对象名 = new 子类名称();
或者:
接口名称 对象名 = new 实现类名称();

下面介绍类中的多态性:
父类:

package cn.itcast.day10.demo04;

public class Fu {

    public void method(){
        System.out.println("父类方法");
    }

    public void methodFu(){
        System.out.println("父类特有方法");
    }
}

子类方法

package cn.itcast.day10.demo04;

public class Zi extends Fu{

    @Override
    public void method(){
        System.out.println("子类方法");
    }
}

main方法

package cn.itcast.day10.demo04;

public class Demo01Multi {


    public static void main(String[] args) {

        // 使用多态的写法
        // 左侧父类的引用,指向了右侧子类的对象
        Fu obj = new Zi();

        obj.method();
        obj.methodFu();
    }
}

运行结果:
在这里插入图片描述
多态中成员变量的访问规则:

访问成员变量的两种方式:

  1. 直接通过对象名称访问成员变量:看等号左边是谁,优先用谁,没有则向上找。
  2. 间接通过成员方法访问成员变量:看该方法属于谁,优先用谁,没有则向上找。

在多态的代码当中,成员方法的访问规则是:
看new的是谁,就优先用谁,没有则向上找。

口诀:编译看左边,运行看右边。

对比一下:
成员变量:编译看左边,运行还看左边。
成员方法:编译看左边,运行看右边。

父类

package cn.itcast.day10.demo05;

public class Fu {

    int num = 10;

    public void showNum(){

        System.out.println(num);

    }

    public void method(){
        System.out.println("父类方法");
    }

    public void methodFu(){
        System.out.println("父类特有方法");
    }
}

子类

package cn.itcast.day10.demo05;

public class Zi extends Fu{

    int num = 20;

    int age = 16;

    @Override
    public void showNum(){
        System.out.println(num);
    }

    @Override
    public void method(){
        System.out.println("子类方法");
    }


    public void methodZi(){
        System.out.println("子类特有方法");
    }


}

main1方法,访问成员变量

package cn.itcast.day10.demo05;

public class Demo01MultiField {

    public static void main(String[] args) {


        // 使用多态的写法,父类引用指向子类对象
        Fu obj = new Zi();

        System.out.println(obj.num);

        System.out.println("=======");

        // 子类没有覆盖重写,就是父:10
        // 子类如果覆盖重写,就是子:20
        obj.showNum();


    }
}

结果如下所示:
在这里插入图片描述
main方法,访问成员方法

package cn.itcast.day10.demo05;

public class Demo02MultiMethod {

    public static void main(String[] args) {

        Fu obj = new Zi();// 多态

        obj.method();// 父子都有,优先用子

        obj.methodFu();//子类没有,父类有,向上查找父类

        // 编译看左边,运行看右边,左边是Fu,Fu当中没有methodZi方法,所以编译报错。
//        obj.methodZi();
    }
}

结果如下所示:
在这里插入图片描述

对象的向上、向下转型

实战一
父类

package cn.itcast.day10.demo06;

public abstract class Animal {

    public abstract void eat();
}

子类1

package cn.itcast.day10.demo06;

public class Cat extends Animal{


    @Override
    public void eat() {
        System.out.println("猫吃鱼");
    }

    // 子类特有方法
    public void catchMouse(){
        System.out.println("猫抓老鼠");
    }
}

子类2

package cn.itcast.day10.demo06;

public class Dog extends Animal{
    @Override
    public void eat() {
        System.out.println("狗吃SHIT");
    }

    public void watchHouse(){
        System.out.println("狗看家");
    }


}

mian函数1

package cn.itcast.day10.demo06;

public class Demo01Main {

    public static void main(String[] args) {

        // 对象的向上的转型,就是:父类引用指向子类对象
        Animal animal = new Cat();
        animal.eat();// 猫吃鱼

        // 向下转型,进行"还原"动作
        Cat cat = (Cat) animal;
        cat.catchMouse();// 猫抓老鼠

        // 下面是错误的向下转型
        // 本来new的时候是一只猫,非要当作狗
        // 错误写法!编译不会报错,但是运行会出现异常
        Dog dog = (Dog) animal;





    }
}

运行结果
在这里插入图片描述
mian方法二
向下转型的判断
如何才能知道一个父类引用的对象,本来是什么子类?
格式:
对象 instanceof 类名称
这将会得到一个boolean值结果,也就是判断前面的对象能不能当做后面类型的实例。

package cn.itcast.day10.demo06;

public class Demo02Instanceof {

    public static void main(String[] args) {
        Animal animal = new Dog();
        animal.eat();// 狗吃SHIT

        // 如果希望调用子类特有的方法,需要向下转型
        // 判断一下父类引用animal本来是不是Dog

        if (animal instanceof Dog){
            Dog dog = (Dog) animal;
            dog.watchHouse();
        }

        // 判断一下animal本来是不是Cat

        if (animal instanceof Cat){
            Cat cat = (Cat) animal;
            cat.catchMouse();


        }

        giveMeAPet(new Dog());


    }

    public static void giveMeAPet(Animal animal){

        if (animal instanceof Dog){
            Dog dog = (Dog) animal;
            dog.watchHouse();
        }

        if (animal instanceof Cat){
            Cat cat = (Cat) animal;
            cat.catchMouse();
        }

    }


}

在这里插入图片描述
实战二(接口中的多态)
computer类

package cn.itcast.day10.demo07;

public class Computer {

    public void powerOn() {
        System.out.println("笔记本电脑开机");
    }

    public void powerOff() {
        System.out.println("笔记本电脑关机");
    }

    // 使用USB设备的方法,使用接口作为方法的参数
    public void useDevice(USB usb) {
        usb.open(); // 打开设备
        if (usb instanceof Mouse) { // 一定要先判断
            Mouse mouse = (Mouse) usb; // 向下转型
            mouse.click();
        } else if (usb instanceof Keyboard) { // 先判断
            Keyboard keyboard = (Keyboard) usb; // 向下转型
            keyboard.type();
        }
        usb.close(); // 关闭设备
    }

}

USB接口

package cn.itcast.day10.demo07;

public interface USB {

    public abstract void open(); // 打开设备

    public abstract void close(); // 关闭设备

}

键盘类实现USB接口

package cn.itcast.day10.demo07;

// 键盘就是一个USB设备
public class Keyboard implements USB {
    @Override
    public void open() {
        System.out.println("打开键盘");
    }

    @Override
    public void close() {
        System.out.println("关闭键盘");
    }

    public void type() {
        System.out.println("键盘输入");
    }
}

鼠标类实现USB接口

package cn.itcast.day10.demo07;

// 鼠标就是一个USB设备
public class Mouse implements USB {
    @Override
    public void open() {
        System.out.println("打开鼠标");
    }

    @Override
    public void close() {
        System.out.println("关闭鼠标");
    }

    public void click() {
        System.out.println("鼠标点击");
    }
}

main方法:

package cn.itcast.day10.demo07;

public class DemoMain {

    public static void main(String[] args) {
        // 首先创建一个笔记本电脑
        Computer computer = new Computer();
        computer.powerOn();

        // 准备一个鼠标,供电脑使用
//        Mouse mouse = new Mouse();
        // 首先进行向上转型
        USB usbMouse = new Mouse(); // 多态写法
        // 参数是USB类型,我正好传递进去的就是USB鼠标
        computer.useDevice(usbMouse);

        // 创建一个USB键盘
        Keyboard keyboard = new Keyboard(); // 没有使用多态写法
        // 方法参数是USB类型,传递进去的是实现类对象
        computer.useDevice(keyboard); // 正确写法!也发生了向上转型
        // 使用子类对象,匿名对象,也可以
//        computer.useDevice(new Keyboard()); // 也是正确写法

        computer.powerOff();
        System.out.println("==================");

        method(10.0); // 正确写法,double --> double
        method(20); // 正确写法,int --> double
        int a = 30;
        method(a); // 正确写法,int --> double
    }

    public static void method(double num) {
        System.out.println(num);
    }

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值