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

Java 抽象类 详解

文章目录

  • 一、概述
    • 1.1、什么是抽象类
    • 1.2、定义抽象类
    • 1.3、什么是抽象方法
    • 1.4、定义抽象方法
  • 二、特点
    • 2.1、抽象类的特点
      • 2.1.1、抽象类不可以实例化对象
      • 2.1.2、抽象类必须要被继承
      • 2.1.3、抽象类的子类
      • 2.1.4、抽象类的成员
    • 2.2、抽象方法的特点
      • 2.2.1、只能有方法声明,不能有方法体
      • 2.2.2、抽象方法只存在于抽象类当中
      • 2.2.3、抽象方法必须要能够被继承
      • 2.2.4、其子类必须要重写抽象方法
  • 三、应用
  • 四、总结

一、概述

1.1、什么是抽象类

    在Java中使用最多的就是类,类用于抽象一类事物,是将现实世界的事物通过抽象的方式给描述成为一个类,该类具有这一类事物的属性和行为,通过new关键字可以实例化类,在程序世界中按照类的描述创建一个对象。而当一个类提供的信息不足以实例化一个具体的对象时,或者说当前类的行为不符合具体对象的行为时,我们是不会将当前类实例化对象的,这种类一般被定义为抽象类。举个例子:定义一个宠物类,其中定义成员属性:姓名、年龄、毛色,定义成员行为:吃饭,睡觉等,这个时候我们看宠物类,宠物宠物,是哪一种动物?有点指代不清,并且不同的宠物吃的东西不一样,宠物狗吃狗粮,宠物猫吃猫粮,也就是说宠物类提供的信息不足以描述一个具体的对象,因此我们不会实例化宠物类这个对象,而是将其设置为抽象类。
    
    简而言之,言而简之,当一个类内部定义的成员变量成员方法不足以描述一个具体的对象时,便将该类定义为抽象类

1.2、定义抽象类

    在Java中,如果被abstract关键字修饰一个类,那么当前类被称之为抽象类

访问修饰符   abstract   class   类名{     }

1.3、什么是抽象方法

    宠物类不是一个具体的动物,那么其内部的eat()方法就无法具体实现,具体的eat()方法只有子类具体的动物对象才可以实现。像这种无法定义具体实现内容的方法我们可以将其设置为抽象方法。

1.4、定义抽象方法

    被abstract关键字修饰方法,那么当前方法被称之为抽象方法,抽象方法不需要写方法体,只有方法声明,没有具体的方法实现,没有{ }。

访问修饰符  abstract  返回类型  方法名(参数列表);
public abstract class Animal {//当前Animal类为抽象类public abstract void eat();//eat()方法为抽象方法public abstract void fly();//fly()方法为抽象方法
}

二、特点

2.1、抽象类的特点

2.1.1、抽象类不可以实例化对象

    本身就是因为当前类提供的信息不足以描述一个具体的类才将当前类设置为抽象类的,而又将抽象类进行实例化对象,那么得到的结果将得不偿失,抽象类不支持实例化对象,也就是不可以通过new关键字实例化对象。

在这里插入图片描述
实例化Animal抽象类,编译直接爆红。

2.1.2、抽象类必须要被继承

    抽象类存在的意义本身就是为了被继承,抽象类没有被继承本身抽象类又不可以实例化对象,那么定义当前抽象类来干什么?

2.1.3、抽象类的子类

    抽象类的子类必须要重写抽象类当中的全部抽象方法,否则一直爆红,即抽象类当中只要是被abstract关键字修饰的方法都被强制重写。

在这里插入图片描述

    有一种方法可以让子类不用重写父类抽象类当中的抽象方法,就是将子类也定义为抽象类,这样当前情况就是抽象类继承抽象类无需重写抽象方法,但是最终还是逃不过重写抽象方法的,该来的还是会来跑不掉的,即便子类是抽象类,那么只要是抽象类结果都是被继承,那么子类抽象类的子类还是要重写抽象方法,而且还是重写父类和父类的父类两个类的抽象方法

在这里插入图片描述

    这也就意味着抽象类的子类可以有两种选择:
1、子类也定义为抽象类
2、子类不是抽象类
不过最终的结果还是继承普通类,即便子类是抽象类也2逃不过被继承的命运最终还是要重写全部都抽象方法

2.1.4、抽象类的成员

    抽象类和普通类基本一致,普通类有的抽象类都有,抽象类当中可以定义成员变量,构造器(同样支持重载),普通成员方法,抽象方法。
    
    唯一和普通类不同的就是:普通类不可以定义抽象方法,抽象类可以定义抽象方法。

public abstract class Animal {//当前Animal类为抽象类protected String name;protected int age;protected String color;public Animal() {}public Animal(String name, int age, String color) {this.name = name;this.age = age;this.color = color;}public void love() {System.out.println(name + "爱主人");}public abstract void eat();//eat()方法为抽象方法public abstract void fly();//fly()方法为抽象方法
}

2.2、抽象方法的特点

2.2.1、只能有方法声明,不能有方法体

    当方法被abstract关键字修饰时,当前方法就是抽象方法,那么当前方法就不能够有具体的实现细节,将方法头编写完整后直接加上“;”,不可以加{ },否则系统会爆红。

在这里插入图片描述

    当方法被关键字abstract修饰时,该方法注定了要被子类重写,因此当前方法没必要再编写具体的实现细节了,语法也不支持编写方法体。

2.2.2、抽象方法只存在于抽象类当中

    抽象类当中可以不包含抽象方法,但是抽象方法必须存在于抽象类当中,这也就意味着:抽象方法不能存在普通类中

在这里插入图片描述

    Dog类是普通类,在Dog类当中编写抽象类,语法不支持,结果就是系统爆红

2.2.3、抽象方法必须要能够被继承

    抽象类存在的意义就是被继承,抽象方法的存在就是被重写,那么抽象方法必须要满足重写的条件,这也就意味着抽象方法不能够被:static关键字,final关键字,private关键字修饰,被这三个关键字修饰的方法都不支持重写

在这里插入图片描述

    也就是说:abstract关键字和static关键字,final关键字,private关键字不能共存,就像是this()和super()不能同时出现一样。

2.2.4、其子类必须要重写抽象方法

    抽象方法存在的意义就是被重写,当子类继承抽象类,如果子类不重写抽象方法,那定义抽象方法有何意义,因此语法要求:其子类(非抽象类)必须重写父类抽象类的抽象方法,否则编译不通过。

在这里插入图片描述

三、应用

public abstract class Animal {//当前Animal类为抽象类protected String name;public Animal(String name) {this.name = name;}public void love() {System.out.println(name + "爱主人");}public abstract void eat();
}class Dog extends Animal {public Dog(String name) {super(name);}@Overridepublic void eat() {System.out.println(name + "吃狗粮....");}
}class Cat extends Animal {public Cat(String name) {super(name);}@Overridepublic void eat() {System.out.println(name + "吃猫粮....");}
}

在这里插入图片描述

四、总结

    可能会有人说:普通的类也可以定义普通方法,然后其继承的子类也可以重写这些普通方法啊,那这样子抽象类有什么意义?定义成为抽象类然后子类一定要重写抽象方法和子类重写普通父类的普通方法有什么区别吗?这不是脱裤子放屁多此一举吗?
    
    事实上使用抽象类相当于多了一层编译器的校验,在很多时候,实际的工作不应该由父类来完成,而应该由子类来完成,父类本身的作用就是实现共性的抽取,实现代码的复用,而且大多数情况下父类所提供的信息都是不足以描述一个具体的对象的。那么此时我们一不小心误用了父类,使用普通方法是不会报错的,但是使用抽象类,当父类实例化的时候会提示错误,让我们尽早的发现并解决问题。这也就意味着抽象类本质上是一种预防出错的机制。

    很多语法存在的意义都是为了“预防出错”例如我们曾经使用fianl关键字,当我们定义变量后,不再对该变量进行更改时,该变量不就相当于是常量吗?但我们使用final关键字时就多了一层预防机制,当我们不小心对该变量进行了修改,编译器就会及时的提醒我们,让我们及时修改错误,避免出现不必要的麻烦。


http://www.mrgr.cn/news/67912.html

相关文章:

  • mysql数据库(三)表的完整性约束、表与表的关系
  • TikTok品牌出海:从“流量为王”到“价值为王”
  • Node.js简介以及安装部署 (基础介绍 一)
  • EPSON机械手与第三方相机的校准功能设计By python
  • 推荐一款强大的图像处理软件:Adobe Photoshop2025
  • 模块化开发 webpack
  • Javascript常见数据结构及其应用场景
  • 【Chapter 2_ Sentosa_DSML Community Edition Product Features】
  • FPGA实战篇:Moore/Mealy状态机
  • 找不到msvcp140.dll怎么办,总结六种解决msvcp140.dll丢失的方法
  • Linux系统-rocky系统安装
  • 《现代网络技术》读书笔记:SDN数据平面和OpenFlow
  • DeFi 4.0峥嵘初现:主权金融时代的来临
  • 《Vue3 报错》Uncaught TypeError: s.finally is not a function
  • Jest项目实战(3):打造完善的开源项目准备指南
  • 面相小白的php反序列化漏洞原理剖析
  • 大模型微调技术 --> LoRA 系列之 LoRA(现今最火热的模型微调方法,甚至没有之一,下面有常用的 lora 参数)
  • ERROR command “uni-serve$1$1“ does not exist.
  • 2024年11月7日练习(滑动窗口算法)
  • Elasticsearch和Lucene之间是什么关系?(ChatGPT回答)
  • 群晖NAS轻松实现文件云同步的解决方案——Cloud Sync!
  • 19.5k star! 告别传统CRM,开源平台Twenty带你进入全新的管理时代(带私活源码)
  • AI变现:AI绘画/AI短剧/AI视频,到底谁该学?
  • springbootHR Nexus人力资源管理系统-计算机毕业设计源码23519
  • SpringBoot续+SpringMVC入门介绍
  • 前后端分离中台管理系统