核心一句话
普通类:可以直接 new 创建实例;
抽象类 abstract class,不能直接 new,用来被继承,提供部分通用模板。
完整对比表
| 对比项 | 普通类(concrete class) | 抽象类 abstract class |
|---|---|---|
| 实例化 | ✅ 可以new 类名()创建对象 | ❌ 不能直接 new;只能被子类继承后,new 子类 |
| 修饰符 | class | abstract class |
| 抽象方法 | ❌ 不能包含抽象方法 | ✅ 可以包含抽象方法(没有方法体void test();)也可以完全没有抽象方法(纯模板抽象类) |
| 构造方法 | 有构造器,new 的时候调用 | 有构造器!只是不能自己 new;子类实例化时,会调用抽象父类构造器 |
| 成员 | 普通属性、普通方法、静态变量 / 方法 | 普通属性、普通方法、静态变量 / 方法、抽象方法 |
| 继承 | 子类继承父类抽象方法,必须重写所有父类抽象方法(如果父类有) | 子类继承抽象类:要么重写全部抽象方法(变成普通类)要么子类也标记 abstract |
| 使用目的 | 描述完整实体,可以直接创建对象使用 | 模板复用:抽取多个子类公共代码;定义子类必须实现的规范 |
详细例子
普通类示例
// 普通类,可以直接 new class Cat { String name; public void say() { System.out.println("喵喵"); } } // 使用 Cat cat = new Cat(); cat.say();抽象类示例(带抽象方法)
// 抽象类 abstract class Animal { String name; // 普通方法,公共逻辑,子类直接复用 public void sleep() { System.out.println("睡觉"); } // 抽象方法:没有方法体,子类必须实现 public abstract void say(); } // 子类继承抽象类,必须实现所有抽象方法 class Dog extends Animal { @Override public void say() { System.out.println("汪汪"); } } // 使用:new 子类,抽象类不能 new Animal dog = new Dog(); dog.say(); dog.sleep();重点坑:抽象类可以没有抽象方法,但只要类加了 abstract,依然不能 new。
abstract class Template { public void commonMethod(){ System.out.println("公共逻辑"); } } // Template t = new Template(); // 编译报错,不能new常见面试问题
1. 抽象类有没有构造方法?
✅有构造方法。抽象类构造器不是给自己实例化用,而是子类实例化时,super()调用,用来初始化抽象类里的成员变量。
2. 抽象方法可以是 static /private/final 吗?
❌ 都不行。
static:静态属于类,抽象方法是留给子类重写,矛盾;private:子类看不到,无法实现;final:final 不能被重写,抽象方法必须被子类实现,矛盾。
3. 抽象类和接口的区别(顺带高频对比)
- 抽象类:
abstract class,单继承;可以有实例变量;可以有构造器;可以有普通方法 + 抽象方法。 - 接口:
interface,多实现;JDK8 前只能常量 + 抽象方法;JDK8 + 有 default/static 方法;无构造器。
抽象类的使用场景
多个类有大量公共代码,但本身这个父类不应该直接实例化,并且部分行为每个子类实现不一样 → 抽象类。
例子: 支付:AliPay、WechatPay,都有公共的校验签名、记录日志;但支付逻辑各不相同。 把公共代码抽到抽象类
AbstractPayment,定义抽象方法pay(),子类实现 pay。