抽象类

1. 什么是抽象类和抽象方法?

  • 多个子类抽取共性时,无法确定方法体,就把父类中的方法定义为抽象
  • 强制让子类按照某种格式重写。因为继承抽象类要么子类也是抽象类,要么子类必须重写父类中的抽象方法
  • 抽象方法所在的类必须是抽象类

2. 抽象类和抽象方法的格式?

  • public abstract 返回值类型 方法名 (参数列表);
  • public abstract class 类名

注意:抽象方法没有方法体,即没有花括号和里面的内容

3. 继承抽象类有哪些要注意?

  • 抽象类不能实例化()
  • 继承抽象类时,要么重写抽象类中的所有抽象方法
  • 要么子类也是一个抽象类,或者我们也可以借助adapter(中间体)重写父类的所有抽象方法,然后让子类继承该类,这样子类就不用重写全部抽象方法,只需要重写自己独有的

4. 为什么抽象类不能实例化?

因为抽象类本身就是 “不完整、未完工” 的类,Java 不允许创建一个不完整的对象。

1. 从语法定义看
抽象类用abstract修饰,它的设计初衷就是:
只做父类,用来被继承,不能自己独立存在

Java语法直接规定:

  • new 抽象类() → 编译报错
  • 只有普通类才能被实例化

2. 从逻辑上看:抽象类是“半成品”

抽象类里可以包含抽象方法:
abstract class Animal {

// 只有声明,没有方法体
public abstract void eat();

}

  • eat() 只是一个约定,没有具体实现
  • 如果能 new Animal(),那调用 eat() 时,JVM 根本不知道要执行什么代码
  • 所以 Java 直接禁止这种逻辑上不完整的对象被创建

3. 从设计目的看

抽象类的作用是:

  • 抽取子类的通用结构
  • 强制子类必须实现某些方法
  • 本身不代表任何具体事物

比如:

  • Animal 是抽象的
  • 真正存在的是 Dog、Cat
  • 你不能造出一个 “抽象的动物”,只能造出具体的狗、猫

4. 那抽象类有构造方法,为什么还不能实例化?

很多人疑惑:
抽象类可以写构造方法,那为什么不能 new?

因为:

  • 抽象类的构造方法不是给自己用的
  • 是给子类构造时调用的(子类 super())
  • 子类实例化时,会先初始化抽象父类的成员,(构造方法只是用来初始化父类的成员变量,而不是只是用来创建对象,创建对象需要包含7个完整的步骤)
  • 抽象类本身依然不能单独 new 出来

另外:

  • 抽象类不一定要有抽象方法
  • 但抽象方法一定要写成抽象类
    不过根据抽象类的设计初衷,通常抽象类都会有抽象方法,否则没有存在的必要

抽象类的应用场景

如果你不知道具体是哪个子类,比如:

Father f = getOneAnimal(); // 可能返回 Son、Daughter、GrandSon...

你不知道它是谁,你没法强转

这时候抽象类就派上用场了。

抽象类的真正作用:统一调用,不用关心具体是谁

不管子类是谁,我都能统一调用同一个方法
abstract class Father {

public abstract void work();

}

class Son extends Father {

@Override
public void work() {
    System.out.println("儿子敲代码");
}

}

class Daughter extends Father {

@Override
public void work() {
    System.out.println("女儿画图");
}

}

写代码的时候就可以直接用父类调用方法:

Father f = new Son();
f.work();

f = new Daughter();
f.work();

  • 不需要强转
  • 不需要判断类型
  • 不需要知道它是谁

这就是多态 + 抽象类的威力:
统一接口,自动适配不同子类

那强转和抽象类的区别是什么?

强转 = 你要“特殊功能”
你要调用子类独有方法,必须强转。

抽象类 = 你要“统一功能”
你要调用所有子类都必须实现的规范方法
直接用父类引用调用即可,不用强转。

一句话终极总结

  • 想调用子类独有功能 → 必须强转
  • 想统一调用所有子类共同的行为 → 用抽象类 / 多态

它们不是替代关系,而是:
抽象类管 “通用规范”
强转管 “特殊需求”

有了抽象类能调用的是父类已经声明过、子类重写了的方法,不是子类自己独有的方法:

父类已经写了这个方法编译器认为“有这个方法”,所以放行
运行时看右边(子类)
真正执行时,JVM去找子类的实现
这才叫多态

强转和抽象类的作用区分

  • 抽象类的目的是子类对方法进行了重写,父类中的方法没有实际用处,因此父类中只定义该方法,将方法和类抽象,从而实现统一调用接口
  • 而强转则是为了实现子类中特有的功能父类中并不存在该方法的定义,编译时无法在父类中找到,这时才去将父类强制类型转换成子类类型,从而编译的时候直接从子类中获取该子类独有的方法

抽象类有构造方法

在Java中,抽象类的构造方法不能直接通过new关键字实例化抽象类本身,但它的核心作用是供子类继承时调用,用于初始化抽象类中定义的成员变量。实际是用于初始化子类的构造方法,因为子类继承了父类的成员变量,在子类的构造方法中通过super()来初始化父类中的成员变量

1. 定义方式:抽象类的构造方法定义和普通类一致,可写无参或有参构造。
2. 子类调用要求:再子类的构造方法必须通过super()显式或隐式调用抽象类的额构造方法,否则编译报错
3. 与接口的区别:接口没有构造方法,因为接口不能定义成员变量,也不存在继承初始化的需求。

posted @ 2026-04-23 08:55  AlexXuu  阅读(5)  评论(0)    收藏  举报