一、抽象类
1.什么是抽象类?
在Java中,抽象类是一种特殊的类,用来表示具有一般特征和行为的抽象概念。它不能够直接实例化,而是作为其他类的基类或者父类来使用。
抽象类就是为了继承而存在的。对于一个父类,如果它的某个方法在父类中实现出来没有任何意义,必须根据子类的实际需求来进行不同的实现,那么就可以将这个方法声明为abstract方法,此时这个类也就成为abstract类了。
class Father{
public void func(){
System.out.println("父类方法");
}
}
class Son extends Father{
@Override
public void func(){
System.out.println("子类重写父类方法");
}
}
public class AbstractClass {
public static void main(String[] args) {
Father father = new Son();
father.func();
}
}
// 输出结果
Connected to the target VM, address: '127.0.0.1:55454', transport: 'socket'
子类重写父类方法
Disconnected from the target VM, address: '127.0.0.1:55454', transport: 'socket'
Process finished with exit code 0
2.抽象类的基本语法
[public] abstract class ClassName {
abstract void fun();
}
- 使用关键字
abstract
来声明抽象类,将类定义为抽象类; - 抽象类可以包含抽象方法和非抽象方法;
- 抽象类不可以被实例化,但是可以被继承;
- 抽象类可以被继承,但不能被标记为
final
,因为它需要被子类扩展和实现; - 抽象类可以包含构造方法,构造方法在子类实例化时调用父类的构造方法;
- 抽象方法使用
abstract
关键字进行声明,并且没有方法体; - 子类必须实现(覆盖、重写)抽象方法,否则子类也要声明为抽象类
3.抽象类的作用
- 实现代码复用:
抽象类可以包含非抽象方法,这些抽象方法的默认行为可以被所有子类共享,从而减少代码重复。 - 建立层次结构:
抽象类可以作为其他类的基类,有助于建立类的层次结构。这种层次结构有助于管理和组织代码,使得相关的类能够清晰地反映出它们之间的关系。 - 实现多态:
通过使用抽象类,可以实现多态,多态允许使用父类类型的引用来调用子类的实现方法。 - 控制子类行为:
抽象类可以包含受保护(protected)或公共(public)的具体方法,这些方法可以被子类调用,通过这种方式,抽象类可以控制和规范子类的行为,确保子类实现特定的功能。 - 隐藏实现细节:
抽象类可以隐藏实现细节,只暴露必要的接口,减少系统的复杂性,并使系统更容易理解和维护。 - 设计模式的实现:
许多设计模式(如模板方法模式、策略模式等)都使用抽象类来定义通用的算法或策略,并通过子类来实现具体的细节。
二、接口
1.什么是接口?
接口(Interface)是一种抽象的参照类型(Reference Type),它定义了一组方法的规范,但没有具体的实现。接口提供了一种契约机制,用于描述类应该具有的行为,而不涉及具体的实现细节。
简单理解,就是两个设备的直接连接方式,例如充电器和充电口、电源插头和电源插座、USB接口等等
2.接口的基本语法
[public] interface InterfaceName {
}
3.接口的特点
- 接口中的成员变量,默认都是被public static final修饰的;
- 接口中的方法,默认都是被public abstract修饰的抽象方法;
- 接口中的普通成员方法,一般是不能有具体的实现内容的;
- 接口中的普通成员方法如果要有具体的实现,必须要被default修饰;
- 接口中可以有静态成员方法;
- 接口不能被实例化;
- 接口中不能有静态代码块、实例代码块以及构造方法;
- 当一个类通过implements实现一个或多个接口后,必须要重写接口中的抽象方法,否则这个类就要被abstract修饰为抽象类;
- 接口可以继承其他接口,使用
extends
关键字进行声明,一个接口可以继承多个接口,实现接口的继承层次结构
4.接口的使用
接口不能直接使用,必须要有一个实现类来实现该接口,并且还要实现接口中的所有抽象方法
以下是实现笔记本电脑使用USB鼠标、USB键盘的例子:
- USB接口:包含打开设备、关闭设备功能
- 笔记本类:包含开机功能、关机功能、使用USB设备功能
- 鼠标类:实现USB接口,并具备点击功能
- 键盘类:实现USB接口,并具备输入功能
// USB接口
interface USB {
// 打开设备
void openDevice();
// 关闭设备
void closeDevice();
}
// 鼠标类,实现USB接口
class Mouse implements USB {
@Override
public void openDevice() {
System.out.println("打开鼠标");
}
@Override
public void closeDevice() {
System.out.println("关闭鼠标");
}
public void click() {
System.out.println("鼠标点击");
}
}
// 键盘类,实现USB接口
class KeyBoard implements USB {
@Override
public void openDevice() {
System.out.println("打开键盘");
}
@Override
public void closeDevice() {
System.out.println("关闭键盘");
}
public void inPut() {
System.out.println("键盘输入");
}
}
// 笔记本类:使用USB设备
class Computer {
public void powerOn() {
System.out.println("打开笔记本电脑");
}
public void powerOff() {
System.out.println("关闭笔记本电脑");
}
public void useDevice(USB usb) {
usb.openDevice();
if (usb instanceof Mouse) {
Mouse mouse = (Mouse) usb;
mouse.click();
} else if (usb instanceof KeyBoard) {
KeyBoard keyBoard = (KeyBoard) usb;
keyBoard.inPut();
}
usb.closeDevice();
}
}
// 测试类:
public class Test2 {
public static void main(String[] args) {
Computer computer = new Computer();
computer.powerOn();
// 使用鼠标设备
computer.useDevice(new Mouse());
// 使用键盘设备
computer.useDevice(new KeyBoard());
computer.powerOff();
}
}
上述代码展示了一个使用USB设备的示例。
首先,定义了一个USB接口,其中包含了openDevice()和closeDevice()两个方法,表示打开和关闭设备的操作。
接着,定义了鼠标类Mouse和键盘类KeyBoard,它们都实现了USB接口,并重写了接口中的方法。除此之外,鼠标类还有一个额外的方法click()表示鼠标的点击操作,键盘类也有一个额外的方法inPut()表示键盘的输入操作。
然后,定义了一个笔记本类Computer,它具有开机和关机的功能,以及一个useDevice()方法用于使用USB设备。useDevice()方法接收一个USB接口的实例作为参数,并根据具体的实例类型执行相应的操作。如果是鼠标设备,就调用鼠标的点击方法;如果是键盘设备,就调用键盘的输入方法。
最后,在测试类Test2中创建了一个笔记本电脑对象,并依次执行了打开电脑、使用鼠标设备、使用键盘设备和关闭电脑的操作。
三、接口和抽象类的区别
1.设计层面不同
抽象类是对一种事物的抽象,即对类抽象,而接口是对行为的抽象。
抽象类是一种提取模板类设计,而接口是行为类设计。简答来讲就是,抽象类就好比把PPT中公共的部分提取成一个模板,公共的地方需要改动,只需要更改提取出来的模板即可,而接口就好比手机的充电口,由最开始的Micro-USB接口改为了Type-C接口后,那么所有手机充电线也都要改为Type-C充电线,也就是要随着接口的变更而变更
2.方法实现不同
抽象类可以包含成员方法的具体实现,但接口只能存在public abstract方法
3.定义关键字不同
接口使用关键字 interface 来定义,抽象类使用关键字 abstract 来定义
4.实现方式不同
接口使用 implements 关键字定义其具体实现,抽象类使用 extends 关键字实现继承
5.静态代码块使用不同
抽象类可以包含静态代码块和静态方法,但接口不能存在
6.子类扩展的数量不同
一个类只能继承一个抽象类,但可以实现多个接口;
7.属性访问控制符不同
抽象类中的成员变量可以是各种类型,但接口中的成员变量只能是public static final