Java的抽象类
- 前言
- 一、抽象类是什么
- 二、抽象类的语法规则
- 示例
- 注意事项
- 抽象类不能直接实例化
- 抽象方法不能是 private 的
- 抽象类中可以包含其他的非抽象方法, 也可以包含字段.
- 三、抽象类的作用
- 四、拓展
- 修饰符的混合使用
前言
推荐一个网站给想要了解或者学习人工智能知识的读者,这个网站里内容讲解通俗易懂且风趣幽默,对我帮助很大。我想与大家分享这个宝藏网站,请点击下方链接查看。 https://www.captainbed.cn/f1
Java的抽象类是一种特殊类,不能被实例化,但可以定义抽象方法和非抽象方法,作为其他类的基类。抽象方法没有具体实现,需在子类中被重写。抽象类用于实现抽象概念或行为,提供统一的接口供子类继承和实现。
一、抽象类是什么
抽象类是一种特殊的类,它不能被实例化,只能被继承。抽象类用来定义一些通用的属性和方法,但这些方法的具体实现是由其子类提供的。抽象类可以包含抽象方法,这些抽象方法没有具体的实现,而是由子类来实现。
抽象类通过使用关键字"abstract
"来声明。当类中存在一个或多个抽象方法时,类必须声明为抽象类。抽象方法使用关键字"abstract
"来声明,并且没有方法体。子类必须实现所有继承自抽象类的抽象方法。
抽象类也可以具有普通的方法和属性,这些方法和属性可以被子类继承和使用。抽象类可以被用作其他类的类型,并且可以作为方法的参数和返回值类型。
抽象类的作用是提供一种模板或骨架,用于定义一组相关的类的共同行为和方法签名。它可以提供一种标准和规范,用于确保子类都具备某些方法的实现,从而避免了代码的重复和冗余。抽象类是面向对象编程中的一个重要概念,它具有继承的特性和多态性。
二、抽象类的语法规则
示例
打印图形
代码语言:javascript复制class Shape {
public void draw() {
// 啥都不用干
}
}
class Cycle extends Shape {
@Override
public void draw() {
System.out.println("○");
}
}
class Rect extends Shape {
@Override
public void draw() {
System.out.println("□");
}
}
class Flower extends Shape {
@Override
public void draw() {
System.out.println("♣");
}
}
/我是分割线//
// Test.java
public class Test {
public static void main(String[] args) {
Shape shape1 = new Flower();
Shape shape2 = new Cycle();
Shape shape3 = new Rect();
drawShape(shape1);
drawShape(shape2);
drawShape(shape3);
}
// 打印单个图形
public static void drawShape(Shape shape) {
shape.draw();
}
}
在打印图形例子中, 我们发现, 父类 Shape
中的 draw
方法好像并没有什么实际工作, 主要的绘制图形都是由Shape
的各种子类的 draw
方法来完成的.
像这种没有实际工作的方法, 我们可以把它设计成一个 抽象方法(abstract method
), 包含抽象方法的类我们称为 抽象类(abstract class
).
abstract class Shape {
abstract public void draw();
}
- 在
draw
方法前加上abstract
关键字, 表示这是一个抽象方法. 同时抽象方法没有方法体(没有{ }
, 不能执行具体代码). - 对于包含抽象方法的类, 必须加上
abstract
关键字表示这是一个抽象类.
注意事项
抽象类不能直接实例化
代码语言:javascript复制Shape shape = new Shape();
// 编译出错
Error:(30, 23) java: Shape是抽象的; 无法实例化
抽象方法不能是 private 的
代码语言:javascript复制abstract class Shape {
abstract private void draw();
}
// 编译出错
Error:(4, 27) java: 非法的修饰符组合: abstract和private
抽象类中可以包含其他的非抽象方法, 也可以包含字段.
这个非抽象方法和普通方法的规则都是一样的, 可以被重写,也可以被子类直接调用
代码语言:javascript复制abstract class Shape {
abstract public void draw();
void func() {
System.out.println("func");
}
}
class Rect extends Shape {
...
}
public class Test {
public static void main(String[] args) {
Shape shape = new Rect();
shape.func();
}
}
// 执行结果
func
三、抽象类的作用
抽象类存在的最大意义就是为了被继承.
抽象类本身不能被实例化, 要想使用, 只能创建该抽象类的子类. 然后让子类重写抽象类中的抽象方法.
有些读者可能会说了, 普通的类也可以被继承呀, 普通的方法也可以被重写呀, 为啥非得用抽象类和抽象方法呢?
确实如此. 但是使用抽象类相当于多了一重编译器的校验.
使用抽象类的场景就如上面的代码, 实际工作不应该由父类完成, 而应由子类完成. 那么此时如果不小心误用成父类了,使用普通类编译器是不会报错的. 但是父类是抽象类就会在实例化的时候提示错误, 让我们尽早发现问题.
很多语法存在的意义都是为了 “预防出错”, 例如我们曾经用过的 final 也是类似. 创建的变量用户不去修改, 不就相当于常量嘛? 但是加上 final
能够在不小心误修改的时候, 让编译器及时提醒我们.充分利用编译器的校验, 在实际开发中是非常有意义的.
四、拓展
修饰符的混合使用
大多数情况下,修饰符是可以混合使用的。
例如:
代码语言:javascript复制public abstract class Transportmeans
但有以下例外:
abstract
不能与final
并列修饰同一个类abstract
不能与private
、static
、final
、native
并列修饰同一个方法abstract
类中不应该有private
的成员(包括属性和方法),因为不能被子类继承,这对abstract
类而言就没有意义了。