主题
Java抽象类、接口与final关键字完全指南
一、核心知识点
1. 抽象类与抽象方法
1.1 抽象的概念

抽象方法和抽象类的形成:
- 抽取出来的方法无法做具体实现,需要延伸到子类中做具体实现,就可以定义成抽象方法
- 抽象方法所在的类一定是抽象类
1.2 定义格式
抽象类定义:
java
public abstract class 类名 {}抽象方法定义:
java
修饰符 abstract 返回值类型 方法名(形参);1.3 使用步骤
- 定义子类,继承抽象父类
- 必须重写父类中所有抽象方法
- 创建子类对象(抽象类不能new对象)
- 调用重写方法
核心意义: 抽象是一种"代码的设计理念",可以将抽象类看做是一类事物的"标准",只要是我的子类,都必须要遵守我的规范,拥有我的功能。
1.4 抽象的注意事项
| 注意事项 | 说明 |
|---|---|
| 不能new对象 | 抽象类不能直接new对象,只能创建非抽象子类的对象 |
| 构造方法 | 抽象类中可以有构造方法,是供子类创建对象时,初始化父类中属性使用的 |
| 成员内容 | 抽象类中可以有成员变量、构造、成员方法 |
| 抽象方法 | 抽象类中不一定非得有抽象方法,但是有抽象方法的类一定是抽象类 |
| 子类要求 | 抽象类的子类,必须重写父类中的所有抽象方法,否则编译无法通过,除非该子类也是抽象类 |
2. 接口
2.1 接口的概念

接口: 是一种标准、规范
2.2 定义格式
接口定义:
java
public interface 接口名 {}实现类定义:
java
public class 实现类 implements 接口 {}2.3 接口中的成员
JDK8之前:
- 抽象方法:
public abstract 返回值类型 方法名(形参)→ 即使不写public abstract,默认也有 - 成员变量:
public static final 数据类型 变量名 = 值→ 即使不写public static final,默认也有
JDK8开始:
- 默认方法:
java
public default 返回值类型 方法名(形参) {
方法体
return 结果
}- 静态方法:
java
public static 返回值类型 方法名(形参) {
方法体
return 结果
}JDK9开始:
- 私有方法:将public改成private
2.4 接口的使用步骤
- 定义接口
- 定义实现类,实现接口
- 重写接口中的所有抽象方法
- 创建实现类对象(接口不能new对象)
- 调用重写方法
2.5 接口的特点
| 特点 | 说明 | 示例 |
|---|---|---|
| 接口多继承 | 一个接口可以继承一个或者多个接口 | public interface 接口A extends 接口B,接口C{} |
| 接口多实现 | 一个实现类可以同时实现一个或者多个接口 | public class 实现类 implements 接口A,接口B{} |
| 继承+实现 | 一个子类可以继承一个父类的同时实现一个或者多个接口 | public class Zi extends Fu implements 接口A,接口B{} |
重要规则:
- 当一个类实现多个接口时,如果接口中的抽象方法有重名且参数一样的,只需要重写一次
- 当一个类实现多个接口时,如果默认方法有重名的,参数一样,默认方法必须要重写一次
2.6 接口和抽象类的区别

相同点:
- 都位于继承的顶端,用于被其他类实现或者继承
- 都不能new
- 都包含抽象方法,其子类都必须重写这些抽象方法
不同点:
| 对比项 | 抽象类 | 接口 |
|---|---|---|
| 定位 | 一般作为父类使用 | 成员单一,抽取的都是方法,是功能的大集合 |
| 成员 | 可以有成员变量、构造、成员方法、抽象方法等 | 主要是抽象方法、常量 |
| 继承 | 类不能多继承 | 接口可以多继承 |
3. final关键字
3.1 final概述
final: 代表的是最终的
3.2 final的使用
| 修饰对象 | 格式 | 特点 |
|---|---|---|
| 类 | public final class 类名{} | 被final修饰的类不能被继承 |
| 方法 | 修饰符 final 返回值类型 方法名(形参){} | 被final修饰的方法不能被重写;final和abstract不能一起使用 |
| 成员变量 | final 数据类型 变量名 | 被final修饰的成员变量,不能二次赋值,相当于常量 |
| 局部变量 | final 数据类型 变量名 = 值 | 不能二次赋值 |
| 对象 | final 类名 对象名 = new 类名() | 被final修饰的对象,地址值不能改变,但是对象的属性值可以改变 |
4. 权限修饰符
4.1 四种权限修饰符
| 修饰符 | 说明 |
|---|---|
| public | 公共的访问权限,被public修饰的在哪里都能使用 |
| protected | 受保护的 |
| 默认 | 成员变量和方法前面的权限修饰符啥也不用,不写 |
| private | 私有的,只能在本类中使用 |
4.2 访问权限表
| public | protected | 默认 | private | |
|---|---|---|---|---|
| 同类 | yes | yes | yes | yes |
| 同包不同类 | yes | yes | yes | no |
| 不同包子父类 | yes | yes | no | no |
| 不同包非子父类 | yes | no | no | no |
4.3 使用建议
- 属性: private修饰 → 封装思想
- 构造: public修饰 → 便于创建对象(工具类除外)
- 方法: public修饰 → 便于调用
二、常见面试题
⭐ 基础题
1. 抽象类必须要有抽象方法吗?
答:不一定。抽象类中不一定非得有抽象方法,但是有抽象方法的类一定是抽象类。
2. 抽象类能使用final修饰吗?
答:不能。抽象类是被用来继承的,final修饰的类不能被继承,两者冲突。
3. 接口中可以有构造方法吗?
答:不能。接口是用来被实现的,不是用来继承的,所以不需要构造方法。
4. 一个类可以实现多个接口吗?
答:可以。一个实现类可以同时实现一个或者多个接口,这是Java实现多继承效果的方式。
⭐⭐ 进阶题
5. 抽象类和接口有什么区别?
答:
相同点:
- 都位于继承的顶端,用于被其他类实现或者继承
- 都不能new对象
- 都包含抽象方法,其子类都必须重写这些抽象方法
不同点:
- 抽象类一般作为父类使用,可以有成员变量、构造、成员方法、抽象方法等
- 接口成员单一,一般抽取接口,抽取的都是方法,是功能的大集合
- 类不能多继承,接口可以多继承
6. 当一个类实现多个接口时,如果接口中有同名同参数的抽象方法,需要重写几次?
答:只需要重写一次。因为方法签名相同,重写一次即可满足所有接口的要求。
7. 当一个类实现多个接口时,如果接口中有同名同参数的默认方法,需要重写吗?
答:必须重写。因为编译器不知道该使用哪个接口的默认方法实现,所以必须由实现类重写该方法。
8. final修饰基本数据类型和引用数据类型有什么区别?
答:
- 基本数据类型: 值不能改变
- 引用数据类型: 地址值不能改变,但是对象内部的属性值可以改变
⭐⭐⭐ 高级题
9. JDK8之后接口中新增的默认方法和静态方法有什么意义?
答:
- 将来开发都是面向接口编程,接口相当于"功能的大集合"
- 如果要临时加一个小功能,不需要几行代码,没必要定义抽象方法再在实现类中实现
- 可以直接在接口中定义默认方法或静态方法,在接口中直接实现
- 默认方法可以被实现类继承和重写,静态方法只能通过接口名调用
10. 什么时候用抽象类?什么时候用接口?
答:
使用抽象类的场景:
- 需要定义一组相关类的通用特征
- 需要共享代码实现
- 需要声明非static和non-final字段
- 需要有构造方法初始化状态
使用接口的场景:
- 需要为不相关的类定义共同的行为
- 需要多继承的效果
- 需要定义行为规范,而不关心具体实现
- 需要利用默认方法提供额外功能
三、实用代码示例
1. 抽象类基础示例
java
public abstract class Animal {
public abstract void eat();
public abstract void drink();
}
public class Dog extends Animal {
@Override
public void eat() {
System.out.println("狗啃骨头");
}
@Override
public void drink() {
System.out.println("狗用舌头卷水喝");
}
}
public class Cat extends Animal {
@Override
public void eat() {
System.out.println("猫吃鱼");
}
@Override
public void drink() {
System.out.println("猫用舌头舔水喝");
}
}
public class Test {
public static void main(String[] args) {
Dog dog = new Dog();
dog.eat();
dog.drink();
Cat cat = new Cat();
cat.eat();
cat.drink();
}
}2. 抽象类构造方法示例
java
public abstract class Employee {
private String name;
private int age;
public Employee() {
}
public Employee(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public abstract void work();
}
public class Teacher extends Employee {
public Teacher() {
}
public Teacher(String name, int age) {
super(name, age);
}
@Override
public void work() {
System.out.println("涛哥在台上叭叭叭讲课");
}
}
public class Test {
public static void main(String[] args) {
Teacher t1 = new Teacher("涛哥", 14);
System.out.println(t1.getName() + "..." + t1.getAge());
t1.work();
}
}3. 接口基础示例
java
public interface USB {
public abstract void open();
public abstract void close();
}
public class Mouse implements USB {
@Override
public void open() {
System.out.println("鼠标打开");
}
@Override
public void close() {
System.out.println("鼠标关闭");
}
}
public class Test {
public static void main(String[] args) {
Mouse m = new Mouse();
m.open();
m.close();
}
}4. 接口默认方法示例
java
public interface USB {
public default void methodDef() {
System.out.println("接口中的默认方法");
}
}
public class Mouse implements USB {
@Override
public void methodDef() {
System.out.println("重写的接口中的默认方法");
}
}
public class Test {
public static void main(String[] args) {
Mouse mouse = new Mouse();
mouse.methodDef();
}
}5. 接口静态方法示例
java
public interface USB {
public static void methodSta() {
System.out.println("接口中的静态方法");
}
}
public class Test {
public static void main(String[] args) {
USB.methodSta();
}
}6. 接口常量示例
java
public interface USB {
public static final int NUM = 10;
int NUM2 = 20;
}
public class Test {
public static void main(String[] args) {
System.out.println(USB.NUM);
System.out.println(USB.NUM2);
}
}7. 接口多实现示例
java
public interface InterfaceA {
public abstract void method();
public abstract void method2();
public default void methodDef() {
System.out.println("接口A中的默认方法");
}
}
public interface InterfaceB {
public abstract void method();
public abstract void method2(int num);
public default void methodDef() {
System.out.println("接口B中的默认方法");
}
}
public class InterfaceImpl implements InterfaceA, InterfaceB {
@Override
public void method() {
System.out.println("重写的默认方法");
}
@Override
public void method2(int num) {
System.out.println("重写的有参的method02");
}
@Override
public void method2() {
System.out.println("重写的无参的method02");
}
@Override
public void methodDef() {
System.out.println("重写的默认方法");
}
}8. final修饰类示例
java
public final class Animal {
}
// 编译错误:无法继承final修饰的类
// public class Dog extends Animal {
// }9. final修饰方法示例
java
public class Animal {
public final void eat() {
System.out.println("吃吃吃");
}
}
public class Dog extends Animal {
// 编译错误:无法重写final修饰的方法
// @Override
// public void eat() {
// }
}10. final修饰对象示例
java
public class Student {
private int id;
private String name;
public Student() {
}
public Student(int id, String name) {
this.id = id;
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
public class Test {
public static void main(String[] args) {
final Student s1 = new Student(1, "张三");
System.out.println(s1);
// s1 = new Student(); // 编译错误:地址值不能改变
s1.setName("李四"); // 正确:属性值可以改变
System.out.println(s1.getName());
}
}四、经典练习题
练习1:员工体系设计
题目描述: 某IT公司有多名员工,按照员工负责的工作不同,进行了部门的划分(研发部、维护部)。
- 研发部(Developer)根据所需研发的内容不同,分为JavaEE工程师、Android工程师
- 维护部(Maintainer)根据所需维护的内容不同,分为网络维护工程师(Network)、硬件维护工程师(Hardware)
公司的每名员工都有他们自己的员工编号、姓名,并要做他们所负责的工作。
工作内容:
- JavaEE工程师:员工号为xxx的xxx员工,正在研发电商网站
- Android工程师:员工号为xxx的xxx员工,正在研发电商的手机客户端软件
- 网络维护工程师:员工号为xxx的xxx员工,正在检查网络是否畅通
- 硬件维护工程师:员工号为xxx的xxx员工,正在修复电脑主板
要求: 根据描述,完成员工体系中所有类的定义,并指定类之间的继承关系。进行XX工程师类的对象创建,完成工作方法的调用。
参考实现:
java
public abstract class Employee {
private int id;
private String name;
public Employee() {
}
public Employee(int id, String name) {
this.id = id;
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public abstract void work();
}
public abstract class Developer extends Employee {
public Developer() {
}
public Developer(int id, String name) {
super(id, name);
}
}
public abstract class Maintainer extends Employee {
public Maintainer() {
}
public Maintainer(int id, String name) {
super(id, name);
}
}
public class JavaEE extends Developer {
public JavaEE() {
}
public JavaEE(int id, String name) {
super(id, name);
}
@Override
public void work() {
System.out.println("员工号为" + getId() + "的" + getName() + "员工,正在研发电商网站");
}
}
public class Android extends Developer {
public Android() {
}
public Android(int id, String name) {
super(id, name);
}
@Override
public void work() {
System.out.println("员工号为" + getId() + "的" + getName() + "员工,正在研发电商的手机客户端软件");
}
}
public class Network extends Maintainer {
public Network() {
}
public Network(int id, String name) {
super(id, name);
}
@Override
public void work() {
System.out.println("员工号为" + getId() + "的" + getName() + "员工,正在检查网络是否畅通");
}
}
public class Hardware extends Maintainer {
public Hardware() {
}
public Hardware(int id, String name) {
super(id, name);
}
@Override
public void work() {
System.out.println("员工号为" + getId() + "的" + getName() + "员工,正在修复电脑主板");
}
}
public class Test {
public static void main(String[] args) {
JavaEE javaEE = new JavaEE(1, "张三");
javaEE.work();
Android android = new Android(2, "李四");
android.work();
Network network = new Network(3, "王五");
network.work();
Hardware hardware = new Hardware(4, "赵六");
hardware.work();
}
}五、学习建议
1. 理解抽象类的设计理念
抽象类不仅仅是语法特性,更是一种设计理念:
- 将抽象类看做是一类事物的"标准"
- 子类必须遵守父类的规范
- 通过抽象方法强制子类实现特定功能
2. 掌握接口的核心作用
接口是Java实现多继承效果的关键:
- 接口是一种标准、规范
- 接口是功能的大集合
- 接口可以实现多继承
3. 理解final的使用场景
final关键字在开发中应用广泛:
- 保护类不被继承(如String类)
- 保护方法不被重写
- 定义常量
- 保护对象引用不被改变
4. 掌握权限修饰符的使用原则
权限修饰符体现了封装思想:
- 属性使用private,实现封装
- 构造方法使用public,方便创建对象
- 方法使用public,方便调用
5. 多练习综合案例
通过综合案例(如员工体系):
- 理解类与类之间的关系
- 掌握继承、抽象、接口的综合应用
- 培养面向对象的设计思维
六、扩展知识
1. 接口与抽象类的选择原则
优先使用接口:
- 需要定义行为规范
- 需要多继承效果
- 不需要共享代码实现
使用抽象类:
- 需要共享代码实现
- 需要定义成员变量
- 需要控制访问权限
2. 设计模式中的应用
模板方法模式:
- 使用抽象类定义算法骨架
- 子类实现具体步骤
策略模式:
- 使用接口定义策略
- 不同实现类代表不同策略
3. JDK中的典型应用
抽象类:
AbstractList:List接口的骨架实现AbstractSet:Set接口的骨架实现AbstractMap:Map接口的骨架实现
接口:
Comparable:自然排序接口Comparator:定制排序接口Cloneable:克隆标记接口
4. 面向接口编程的思想
核心思想:
- 定义接口作为契约
- 面向接口编程,而不是面向实现编程
- 提高代码的灵活性和可扩展性
优势:
- 降低耦合度
- 提高代码复用性
- 便于系统扩展和维护
学习提示:
- 重点理解抽象类和接口的设计思想
- 多写代码练习,掌握各种使用场景
- 结合实际项目理解面向接口编程的优势
- 注意final关键字在各种场景下的使用限制