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

[Java 基础]抽象类和接口

在继承体系中,父类有时不需要实现某些方法,或者某些方法的实现不确定,应该如何处理?抽象类就是解决这个问题的。

抽象类

抽象类的定义和特性

定义: 使用 abstract 关键字修饰的类。

特性:

抽象类不能被实例化(不能使用 new 关键字创建对象)。

抽象类可以包含抽象方法和非抽象方法。

抽象类可以包含成员变量、构造方法和静态成员。

如果一个类包含抽象方法,那么这个类必须声明为抽象类。

子类继承抽象类后,必须实现父类中所有的抽象方法,除非子类也是抽象类。

抽象方法的概念和定义

定义: 使用 abstract 关键字修饰的方法,没有方法体(以分号结尾)。

作用: 声明一个方法的存在,要求子类必须提供具体的实现。

语法: public abstract void methodName(参数列表); (访问修饰符可以是 public、protected,不能是 private、static、final、native、synchronized)

抽象类的使用场景和意义

定义共同的模板: 抽象类可以作为一组相关类的通用父类,定义它们的共同行为和属性,将具体的实现延迟到子类。

强制子类实现某些行为: 通过抽象方法,强制子类必须实现特定的功能。

代码重用: 抽象类可以包含非抽象方法,提供一些通用的实现,供子类直接使用,提高代码的复用性。

案例分析:图形类

创建一个抽象类 Shape,包含一个抽象方法 calculateArea() 用于计算面积。

创建 Circle 和 Rectangle 类继承 Shape,并实现 calculateArea() 方法。

演示如何使用父类引用指向子类对象,并调用 calculateArea() 方法(多态)。

// 抽象类 Shape
abstract class Shape {protected String color;public Shape(String color) {this.color = color;}public String getColor() {return color;}// 抽象方法,计算面积public abstract double calculateArea();// 非抽象方法,显示信息public void display() {System.out.println("这是一个" + getColor() + "的形状。");}
}// 圆形类
class Circle extends Shape {private double radius;public Circle(String color, double radius) {super(color);this.radius = radius;}public double getRadius() {return radius;}@Overridepublic double calculateArea() {return Math.PI * radius * radius;}
}// 矩形类
class Rectangle extends Shape {private double width;private double height;public Rectangle(String color, double width, double height) {super(color);this.width = width;this.height = height;}public double getWidth() {return width;}public double getHeight() {return height;}@Overridepublic double calculateArea() {return width * height;}
}public class AbstractClassDemo {public static void main(String[] args) {// Shape s = new Shape("红色"); // 错误:抽象类不能被实例化Circle circle = new Circle("蓝色", 5.0);Rectangle rectangle = new Rectangle("绿色", 4.0, 6.0);circle.display();System.out.println("圆的面积:" + circle.calculateArea());rectangle.display();System.out.println("矩形的面积:" + rectangle.calculateArea());Shape s1 = new Circle("黄色", 3.0); // 父类引用指向子类对象System.out.println("形状1的面积:" + s1.calculateArea());Shape s2 = new Rectangle("橙色", 2.0, 8.0); // 父类引用指向子类对象System.out.println("形状2的面积:" + s2.calculateArea());}
}

Java 中常见的抽象类

AbstractList:帮助你快速构建自己的 List 类型

接口

继承一般是子类和父类是有种关联的,比如父类是一种更大的概念。抽象类解决的是父类有时不需要实现某些方法,或者某些方法的实现不确定这种问题。 如果一个类需要同时具备多种不相关的能力(行为),例如既能跑又能飞,单继承机制如何实现?

接口的概念和特性

  • 定义: 使用 interface 关键字声明的类型。
  • 特性:
    • 接口不是类,它是一种规范或契约
    • 接口中只能包含常量(public static final 修饰)和抽象方法(public abstract 修饰,可以省略这两个关键字,Java 9 之后可以包含 defaultstatic 方法)
    • 接口不能被实例化
    • 一个类可以实现(implements)多个接口
    • 实现接口的类必须实现接口中所有的抽象方法
public interface InterfaceName {// 常量声明 (public static final)数据类型 CONSTANT_NAME =;// 抽象方法声明 (public abstract)返回类型 methodName(参数列表);// Java 8 允许定义 default 方法default 返回类型 defaultMethodName(参数列表) {// 默认实现}// Java 8 允许定义 static 方法static 返回类型 staticMethodName(参数列表) {// 静态实现}
}

接口的实现

  • 使用 implements 关键字实现一个或多个接口
  • 实现类必须提供接口中所有抽象方法的具体实现
  • 如果一个类实现了多个接口,需要实现所有接口中的所有抽象方法

接口的使用场景和意义

  • 实现多继承的效果: 通过实现多个接口,一个类可以拥有多个接口定义的能力
  • 定义规范和契约: 接口定义了一组方法签名,任何实现该接口的类都必须遵守这些规范
  • 实现松耦合: 接口将行为的定义与具体的实现分离,使得代码更加灵活和可维护
  • 实现回调机制: 接口可以作为回调函数的类型,实现不同模块之间的交互
// 可飞翔接口
interface Flyable {void fly();
}// 可游泳接口
interface Swimmable {void swim();
}// 鸟类
class Bird implements Flyable {private String name;public Bird(String name) {this.name = name;}public String getName() {return name;}@Overridepublic void fly() {System.out.println(name + "正在飞翔。");}
}// 鱼类
class Fish implements Swimmable {private String name;public Fish(String name) {this.name = name;}public String getName() {return name;}@Overridepublic void swim() {System.out.println(name + "正在游泳。");}
}// 鸭子类,同时实现 Flyable 和 Swimmable 接口
class Duck implements Flyable, Swimmable {private String name;public Duck(String name) {this.name = name;}public String getName() {return name;}@Overridepublic void fly() {System.out.println(name + "正在用翅膀飞翔。");}@Overridepublic void swim() {System.out.println(name + "正在水中游泳。");}
}public class InterfaceDemo {public static void main(String[] args) {Bird bird = new Bird("老鹰");Fish fish = new Fish("金鱼");Duck duck = new Duck("唐老鸭");bird.fly();fish.swim();duck.fly();duck.swim();Flyable f = new Duck("小黄鸭"); // 接口引用指向实现类对象f.fly();Swimmable s = new Duck("大白鹅"); // 接口引用指向实现类对象s.swim();}
}

Java 中常用的接口

Comparable 接口(rt.jar 下的 java.lang.Comparable)

List 接口(rt.jar 下的 java.util.List)

还有很多 Java 自带的接口,都是定义了一个规范,实现这个接口就代表了你遵循了某种规范。

接口和抽象类的区别

如何选择抽象类和接口

  • 关注“是什么”的关系 (Is-A): 如果你正在定义一个类的层次结构,并且子类在本质上是父类的一种特殊类型,并且需要共享一些共同的实现,那么应该使用抽象类
  • 关注“能做什么”的能力 (Can-Do): 如果你正在定义一组类应该具备的某种能力或行为,而这些类在本质上可能没有继承关系,那么应该使用接口
  • 需要定义共同的实现: 如果需要在父类中提供一些通用的方法实现,供子类直接使用,那么应该使用抽象类
  • 需要实现多继承的效果: 如果一个类需要同时具备多种不同的能力,那么应该使用接口
  • 设计 API 规范: 接口非常适合定义 API 的规范,强制实现类遵循特定的方法签名

总结

  • 抽象类和接口都是 Java 中实现多态的重要机制
  • 抽象类更侧重于代码的复用和类型的继承关系
  • 接口更侧重于定义行为的规范和实现类具备的能力
  • 在实际开发中,需要根据具体的需求选择合适的机制

相关文章:

  • 【C/C++】析构函数好玩的用法:~Derived() override
  • MCP与检索增强生成(RAG):AI应用的强大组合
  • 卫星的“太空陀螺”:反作用轮如何精准控制姿态?
  • 十六、【前端强化篇】完善 TestCase 编辑器:支持 API 结构化定义与断言配置
  • leetcode 455. Assign Cookies和2410. Maximum Matching of Players With Trainers
  • Redis命令使用
  • 神经网络-Day44
  • LabVIEW的MathScript Node 绘图功能
  • 【开源工具】基于PyQt5工作时长计算器工具开发全解析
  • 【Blender Texture】【游戏开发】高质感 Blender 4K 材质资源推荐合集 —— 提升场景真实感与美术表现力
  • 基于BP神经网络的语音特征信号分类
  • web全栈开发学习-01html基础
  • 服务器中僵尸网络攻击是指什么?
  • 机器学习算法分类
  • 聊聊FlaUI:让Windows UI自动化测试优雅起飞!
  • 卫星在轨姿态控制技术详解:从自旋稳定到高精度闭环控制
  • SimpleDateFormat 和 DateTimeFormatter 的异同
  • lc hot 100之:dummy哨兵节点创建方法
  • 每天总结一个html标签——Audio音频标签
  • 代码训练LeetCode(21)跳跃游戏2
  • 昆山网站建设公司/免费站推广网站2022
  • php做网站的公司有哪些/网络媒体广告代理
  • 可以免费做推广的网站/近期时政热点新闻20条
  • 照明网站建设/优化关键词排名外包
  • web前端开发盒子模型/爱站seo查询软件
  • 电商网站设计思维导图/企业网站设计优化公司