一、前言
记录时间 [2024-05-15]
系列文章简摘:
面向对象 03:类与对象的创建、初始化和使用,通过 new 关键字调用构造方法,以及创建对象过程的内存分析
面向对象 04:三大特性之——封装,封装的含义和作用,以及在 Java 中的使用方式,附完整的测试案例代码
面向对象 05:三大特性之——继承,继承在 Java 中的相关使用,区分关键字 super 和 this,方法重写的注意点
面向对象 06:三大特性之——多态,多态的基本概念和相关使用,关键字 instanceof,以及对象间的类型转换
更多 Java 相关文章,请参考专栏哦。
本文讲述了 Java 面向对象编程中的重要概念——抽象类的相关知识,包括基本概念、如何使用,以及一些注意事项。
二、基本概念
在 Java 中,抽象类(Abstract Class)是一种不能被实例化的类,它的主要目的是为了提供一个类族的通用模板。
抽象类可以包含抽象方法(abstract methods)和具体方法(concrete methods)。
抽象类是 Java 面向对象编程中的一个重要概念,它有助于实现软件的模块化、扩展性和可维护性。
1. 抽象方法
抽象方法是没有具体实现的方法,它只有声明而没有方法体,即没有花括号 {}
包裹的代码部分,并且必须在方法声明中使用 abstract
关键字。
抽象方法需要在其子类中被具体实现。
- 如果一个非抽象类继承了某个抽象类,那么这个非抽象类要具体实现抽象类的抽象方法。
- 但如果是另一个抽象类继承了某个抽象类,就不需要具体实现。
2. 具体方法
具体方法是指那些有完整实现的方法,即包含方法声明和方法体的方法。与之相对的是抽象方法,抽象方法只有声明没有实现。
具体方法是实际执行代码的地方,它们完成了类或接口所声明的功能。
具体方法的定义包括:
- 访问修饰符:如
public
、protected
、private
等; - 返回值类型,如果方法不返回任何值,则用
void
表示; - 方法名、参数列表(如果有),以及方法体。
- 方法体由一对大括号
{}
包围,里面包含了该方法执行的具体逻辑代码。
以下是一个具体方法的例子:
在这个例子中,Calculator
类有一个名为 add
的具体方法,它接受两个整数参数 num1
和 num2
,并返回它们的和。
public class Calculator {
// 具体方法:计算两数相加
public int add(int num1, int num2) {
return num1 + num2;
}
}
三、抽象类的使用
1. 为什么使用抽象类
- 设计模板:抽象类为子类提供了一个公共的接口和实现框架,确保了子类具有统一的结构。
- 代码复用:通过包含具体方法,抽象类可以提供通用功能的实现,避免重复代码。
- 强制实现:要求子类必须实现某些方法,保证了类型的一致性。
2. 定义抽象类
要定义一个抽象类,需要在类的声明前加上 abstract
关键字。
抽象方法必须写在抽象类中。
例如,Animal
是一个抽象类,它包含一个抽象方法 eat()
和一个具体方法 sleep()
。
public abstract class Animal {
// 抽象方法,是一种约束
// 只有方法名字,没有方法的实现
public abstract void eat();
// 具体方法
public void sleep() {
System.out.println("Zzz...");
}
}
3. 继承抽象类
子类继承抽象类时,如果子类不是抽象类,那么它必须实现父类中的所有抽象方法。
子类继承抽象类,使用 extends
关键字,属于单继承。
例如,在这个例子中,Dog
类继承了 Animal
类,并实现了 eat()
方法。
// 继承抽象类的子类,必须要实现抽象类中的所有抽象方法
// 子类不是抽象类
public class Dog extends Animal {
@Override
public void eat() {
System.out.println("Dog is eating.");
}
}
四、注意事项
- 抽象类不能被实例化,即,不能直接创建一个抽象类的对象。
- 如果一个类包含了至少一个抽象方法,那么这个类必须声明为抽象的。
- 抽象类可以有构造方法,用于被其子类调用初始化共通的属性或进行一些初始化操作。
- 抽象类的子类可以是抽象的,也可以是非抽象的。
1. 抽象类不能创建对象
抽象类不能使用 new
关键字直接创建对象。
原因:抽象类的主要目的是作为一个基类来提供其他类继承的通用接口或共享的实现,它可能包含未实现的抽象方法,这些方法需要在具体的子类中得到实现。
当试图使用 new
关键字实例化一个抽象类时,Java 编译器会报错,提示不能实例化抽象类。
如何用抽象类的特性:
- 创建一个继承自该抽象类的具体子类;
- 并在子类(非抽象类)中实现所有的抽象方法;
- 然后通过这个子类来创建对象。
例如,在这个例子中,虽然我们不能直接创建 Animal
类的实例,但我们可以通过创建其子类 Dog
的实例,并通过多态的方式,让 myDog
引用指向 Dog
对象,从而间接使用抽象类 Animal
定义的结构。
// 抽象类
abstract class Animal {
abstract void sound();
}
// 具体子类
class Dog extends Animal {
void sound() {
System.out.println("The dog barks.");
}
}
// 创建对象
public class Main {
public static void main(String[] args) {
// 错误
// 不能这样创建:Animal animal = new Animal();
// 应该这样
Animal myDog = new Dog();
myDog.sound(); // 输出:The dog barks.
}
}
2. 抽象类有构造方法
虽然抽象类不能使用 new
关键字直接创建对象,但抽象类可以有构造方法 constructor
。
构造方法在抽象类中主要有如下用途:
- 初始化抽象类的成员变量
- 抽象类可能包含实例变量,构造方法可以用来初始化这些变量。
- 这对于确保抽象类的子类继承了恰当的状态是非常有用的。
- 被子类构造方法调用
- 当一个子类继承抽象类时,子类的构造方法默认会调用父类(这里指抽象类)的无参构造方法,除非子类构造方法中显式地调用了父类的其他构造方法。
- 这意味着,即使不能直接创建抽象类的实例,它的构造方法也会在创建子类实例时被调用到。
例如,在下面这个例子中,抽象类 Animal
有一个带参数的构造方法,用于设置动物的名字。子类 Dog
的构造方法通过 super
关键字调用了父类的构造方法来初始化 name
成员变量。
这表明,即使抽象类本身不能被实例化,其构造方法仍然是有意义且必要的。
abstract class Animal {
String name;
// 抽象类的构造方法
public Animal(String name) {
// 初始化name成员变量
this.name = name;
}
abstract void sound();
}
class Dog extends Animal {
public Dog(String name) {
// 子类构造方法调用父类(抽象类)的构造方法
super(name);
}
@Override
void sound() {
System.out.println(name + " says Woof!");
}
}
public class Main {
public static void main(String[] args) {
Dog myDog = new Dog("Buddy");
myDog.sound(); // 输出:Buddy says Woof!
}
}
五、总结
本文讲述了 Java 面向对象编程中的重要概念——抽象类的相关知识,包括基本概念、如何使用,以及一些注意事项。
一些参考资料
狂神说 Java 零基础:https://www.bilibili.com/video/BV12J41137hu/
TIOBE 编程语言走势: https://www.tiobe.com/tiobe-index/
Typora 官网:https://www.typoraio.cn/
Oracle 官网:https://www.oracle.com/
Notepad++ 下载地址:https://notepad-plus.en.softonic.com/
IDEA 官网:https://www.jetbrains.com.cn/idea/
Java 开发手册:https://developer.aliyun.com/ebook/394
Java 8 帮助文档:https://docs.oracle.com/javase/8/docs/api/