当前位置: 首页 > ai >正文

零基础 “入坑” Java--- 十二、抽象类和接口

文章目录

  • 一、抽象类
    • 1.何为抽象类
    • 2.抽象类语法
    • 3.抽象类特性
    • 4.抽象类作用
  • 二、接口
    • 1.何为接口
    • 2.接口语法及特性
  • 三、接口使用
  • 四、实现多个接口
  • 五、接口间的继承
  • 六、抽象类和接口的区别

一、抽象类

1.何为抽象类

在面向对象的思想中,所有的对象都是通过类来描述的;但是,并不是所有的类都是用来描述对象的,当一个类中没有包含足够的信息来描述一个具体的对象时,我们就将这样的类称为抽象类。

我们之前经常使用到的Animal类就可以被设计为一个抽象类。

2.抽象类语法

在Java中,被abstract修饰的类称为抽象类;被abstract修饰的方法称为抽象方法,抽象方法不用给出具体的实现(我们以Animal类为例):

//抽象类
abstract class Animal {public String name;public int age;//抽象方法abstract public void eat();
}

注意:

1.抽象类也是类,在抽象类中可以包含普通成员方法和普通成员变量以及构造方法。
2.抽象类的构造方法依靠子类的调用,帮助抽象类初始化成员。
3.当一个类中有抽象方法时,那么该类一定为抽象类。
4.抽象类中不一定有抽象方法。

3.抽象类特性

当我们定义完一个抽象类之后,我们想去使用,此时我们尝试使用抽象类实例化一个对象:

    public static void main(String[] args) {Animal animal = new Animal();}

在编写代码时程序会报错,编译器会提示我们抽象类不能被实例化。

一个类不能被实例化,那么这个类是干什么的呢?抽象类就是为了被继承的:

class Dog extends Animal {}

当我们定义一个狗类继承动物类时,此时代码会报错,这又是为什么呢?

当一个普通的类继承抽象类之后,在普通类中一定要重写抽象类中所有的抽象方法:

class Dog extends Animal {@Overridepublic void eat() {System.out.println("吃狗粮");}
}

此时,代码就可以正常运行。

对于抽象类我们还需要知道:抽象方法不能被final、static和private修饰,因为抽象方法在子类中一定要被重写。

当一个普通类A继承了抽象类B之后,不想重写B中的抽象方法,可以将普通类A也设计为抽象类;但是当另一个普通类C继承抽象类A之后,需要重写A和B中所有的抽象方法。


使用抽象类时,依旧可以发生向上转型和动态绑定

abstract class Animal {public String name;public int age;abstract public void eat();
}
class Dog extends Animal {@Overridepublic void eat() {System.out.println("吃狗粮");}
}
class Cat extends Animal {@Overridepublic void eat() {System.out.println("吃猫粮");}
}
public class Test {public static void test(Animal animal) {animal.eat();}public static void main(String[] args) {//向上转型Animal animal = new Dog();Animal animal1 = new Cat();test(animal);test(animal1);test(new Dog());}
}

在传递参数的时候,我们也可以使用匿名对象,如"new Dog()";但是,匿名对象也有缺点:每次使用都需要重新实例化。

4.抽象类作用

抽象类并不能被实例化,主要就是用来被继承的,那抽象类的存在有什么意义呢?

当我们使用抽象类时,就相当于增加了一重编译器的校验,通过编译器提示可能出现的问题,帮助我们尽早发现。

抽象类存在的意义就是为了让编译器进行更好的校验,如:像Animal这样的类我们并不会直接使用,而是使用其子类,但万一我们创建了一个Animal的实例,编译器就会及时提醒我们。

二、接口

1.何为接口

接口在我们的生活中随处可见,笔记本电脑上的USB接口,墙上的电源接口等等。在Java中,也存在接口的概念:在Java中,接口可以理解为多个类的公共规范,是一种引用数据类型。

2.接口语法及特性

接口的语法定义格式与类的语法定义格式基本相同,只需将class换为interface关键字即可。

interface IAnimal {}

此时,我们就定义了一个接口。

我们想在接口中添加一些变量和方法:

interface IAnimal {int a = 10;void test();public static final int b = 20;public abstract void test1();
}

以上这两种写法都是可以的:

1.接口中的成员变量默认为"public static final"修饰的,可省略不写。
2.接口中的成员方法默认为"public abstract"修饰的,可省略不写。

原则上来说,在接口中不可以存在普通的成员方法

interface IAnimal {//errorpublic void test2() {}
}

但是,从Java8开始,允许在接口中定义一个default方法,此方法可以有具体的实现

interface IAnimal {default public void test2() {System.out.println("嘻嘻");}
}

在接口中,被static修饰的方法,也可以有具体的实现

interface IAnimal {public static void test3() {System.out.println("嘿嘿");}
}

接口不能通过new来实例化对象

    public static void main(String[] args) {//errorIAnimal iAnimal = new IAnimal();}

类和接口之间,可以通过implements关键字来实现接口

class Dog implements IAnimal {}

但此时代码会报错,这是因为接口中存在抽象方法,我们需要对抽象方法进行重写

class Dog implements IAnimal {@Overridepublic void test() {}@Overridepublic void test1() {}
}

此时,代码就可以正常运行。


在使用接口时,我们还需注意:

1.接口也可以发生向上转型和动态绑定。
2.重写接口中的抽象方法时,必须使用public修饰,因为重写的 方法的 访问权限 不能比 被重写的 方法的 访问权限低。
3.接口中不能存在静态代码块和构造方法。
4.一个接口也会产生独立的字节码文件(×××.class)。
5.当一个类没实现接口中所有的抽象方法时,该类一定为抽象类。

6.父类和子类之间是继承关系(extends),类和接口之间是实现关系(implements)。

三、接口使用

接口不能直接使用,需要有一个类来实现接口,并重写接口中所有的抽象方法。


我们举个例子来熟悉一下接口的使用:

定义一个接口:USB,接口中包含打开设备功能,关闭设备功能。
定义一个鼠标类:实现USB接口,并具备点击功能。
定义一个键盘类:实现USB接口,并具备输入功能。
定义一个笔记本类:包含开机,关机及使用USB设备功能。

根据题意,我们先定义一个接口:

public interface IUSB {void openDevice(); //打开设备void closeDevice(); //关闭设备
}

定义一个鼠标类实现接口(注意:重写抽象方法):

public class Mouse implements IUSB {@Overridepublic void openDevice() {System.out.println("打开鼠标");}@Overridepublic void closeDevice() {System.out.println("关闭鼠标");}public void click() {System.out.println("点击功能");}
}

定义一个键盘类实现接口(注意:重写抽象方法):

public class Keyboard implements IUSB {@Overridepublic void openDevice() {System.out.println("打开键盘");}@Overridepublic void closeDevice() {System.out.println("关闭键盘");}public void inPut() {System.out.println("输入功能");}
}

定义一个笔记本类,包含开机关机功能:

public class Computer {public void open() {System.out.println("打开笔记本");}public void close() {System.out.println("关闭笔记本");}public void use(IUSB iusb) {iusb.openDevice();//向下转型if (iusb instanceof Mouse) {Mouse mouse = (Mouse) iusb;mouse.click();} else if (iusb instanceof Keyboard) {Keyboard keyboard = (Keyboard) iusb;keyboard.inPut();}iusb.closeDevice();}//测试public static void main(String[] args) {Computer computer = new Computer();computer.open();computer.use(new Mouse());computer.use(new Keyboard());computer.close();}
}

运行结果为:
在这里插入图片描述

四、实现多个接口

在Java中,类和类之间是不支持多继承的,但是一个类可以实现多个接口。

我们举个例子来说明一下:

定义三个接口,分别表示三种功能:飞、跑、游:

public interface IFlying {void fly();
}
public interface IRunning {void run();
}
public interface ISwimming {void swim();
}

再定义一个动物类,定义为抽象类,因为类中需要有被重写的eat抽象方法:

abstract public class Animal {public String name;public int age;public abstract void eat();public Animal(String name) {this.name = name;}
}

再定义一个狗类,继承动物类,并实现跑和游的接口:

public class Dog extends Animal implements IRunning,ISwimming {public Dog(String name) {super(name);}@Overridepublic void eat() {System.out.println(name + "吃狗粮");}@Overridepublic void run() {System.out.println(name + "小狗跑");}@Overridepublic void swim() {System.out.println(name + "小狗游");}
}

在狗类中,我们要重写继承和实现的所有抽象方法。

再定义一个鸟类,继承动物类,并实现跑和飞的接口:

public class Bird extends Animal implements IFlying,IRunning {public Bird(String name) {super(name);}@Overridepublic void eat() {System.out.println(name + "吃鸟粮");}@Overridepublic void fly() {System.out.println(name + "小鸟飞");}@Overridepublic void run() {System.out.println(name + "小鸟跑");}
}

同样,在鸟类中,我们要重写继承和实现的所有抽象方法。

我们再给一个测试类,用来测试写过的代码:

public class Test {public static void test1(Animal animal) {animal.eat();}public static void test2(IRunning iRunning) {iRunning.run();}public static void test3(IFlying iFlying) {iFlying.fly();}public static void test4(ISwimming iSwimming) {iSwimming.swim();}public static void main(String[] args) {}
}

此时,代码的使用就会非常灵活:

    public static void main(String[] args) {Dog dog = new Dog("小狗");Bird bird = new Bird("小鸟");test1(dog);test1(bird);System.out.println("===========");test2(dog);test2(bird);System.out.println("===========");//test3(dog); error:没实现此接口test3(bird);System.out.println("===========");test4(dog);//test4(bird); error:没实现此接口}

运行结果为:
在这里插入图片描述
对于test2,test3,test4方法,方法的参数为接口类型,当调用方法时,只要传递的参数实现了这个接口,就可以使用。因此,我们还可以这样使用接口:

我们再定义一个车类,实现跑的接口:

public class Car implements IRunning {@Overridepublic void run() {System.out.println("小车跑");}
}

此时,在测试类中调用test2方法,并将实例化的小车作为参数进行传递,代码可以正常运行:

    public static void main(String[] args) {test2(new Car()); //小车跑}

当使用了接口时,就无需关注类的类型,只需考虑类是否实现了接口,具不具备接口中的功能即可,大大提高了代码的灵活性。

五、接口间的继承

在Java中,类和类之间不能是多继承关系的,但是接口和接口之间可以实现多继承,即可以使用接口达到多继承的目的。

接口使用 extends关键字 拓展(继承)一个接口,从而达到代码复用的效果:

interface A {void testA();
}
interface B {void testB();
}
interface C extends A,B {void testC();
}
public class Test implements C {@Overridepublic void testA() {}@Overridepublic void testB() {}@Overridepublic void testC() {}
}

在上面这个例子中,接口C继承了接口A和接口B,表示C这个接口具备了B接口和A接口的功能,当一个普通类实现C接口时,需要重写A、B、C中所有的抽象方法

六、抽象类和接口的区别

二者的核心区别在于:抽象类中可以包含普通方法和普通变量,而接口中不能包含普通方法。

在这里插入图片描述


Ending。

http://www.xdnf.cn/news/15767.html

相关文章:

  • ndexedDB 与 LocalStorage:全面对比分析
  • aosp15实现SurfaceFlinger的dump输出带上Layer详细信息踩坑笔记
  • EP01:【Python 第一弹】基础入门知识
  • Vue rem回顾
  • 文档表格标题跑到表格下方,或标题跟表格空隔太大如何处理
  • Java无服务架构新范式:Spring Native与AWS Lambda冷启动深度优化
  • Flutter基础(前端教程①⑤-API请求转化为模型列成列表展示实战)
  • 财务数字化——解读财务指标及财务分析的基本步骤与方法【附全文阅读】
  • Error:HTTP Status 405 - HTTP method POST is not supported by this URL
  • 大数据之路:阿里巴巴大数据实践——日志采集与数据同步
  • 短视频矩阵的未来前景:机遇无限,挑战并存
  • [spring6: Advice Advisor Advised]-快速理解
  • stm32继电器使用方法
  • 【HarmonyOS】Ability Kit - Stage模型
  • 2023 年 5 月青少年软编等考 C 语言八级真题解析
  • 安装tomcat启动startup.bat出现闪退问题
  • 驾驭 Spring Boot 事件机制:8 个内置事件 + 自定义扩展实战
  • windows wsl ubuntu 如何安装 maven
  • 前端知识回顾-登录界面
  • 实现el-select下拉框,下拉时加载数据
  • 【RK3576】【Android14】摄像头MIPI开发调试
  • [Python] -实用技巧10- 时间处理:datetime 和 time 模块入门
  • 【数据结构初阶】--双向链表(二)
  • 跨境卖家紧急自查,Endryko Karmadi四季版画版权维权
  • 【嵌入式电机控制#16】电流环(三):过采样提高采集精度看门狗监测总线电压
  • 【Linux系统】进程控制
  • 从0开始学习R语言--Day51--PH检验
  • OpenCV 官翻 1 -介绍、安装、功能概览、核心操作
  • 云计算与 DevOps(开发与运维)
  • sqli-labs靶场通关笔记:第32-33关 宽字节注入