引入
- 我们经常使用一个父类来管理多个子类,父类中有大多数子类都需要的属性和方法,比如例子中的Animal类,给其他动物提供了基本的吃饭和发出叫声的方法,如下方代码所示:
package com.abs;
public class Animal {
public void eat(){
System.out.println("我是一个动物,我正在吃饭");
}
public void makeSound(){
System.out.println("我是一个动物,我会哇哇叫");
}
}
- 这是子类Dog和Cat,因猫叫和狗叫是不同的,虽然都是叫,但是细节不同,这时候我们就需要对这两个子类的方法进行重写,如下方代码所示:
package com.abs;
public class Dog extends Animal {
@Override
public void makeSound() {
System.out.println("我是狗子,我会汪汪汪!");
}
@Override
public void eat() {
System.out.println("我正在吃骨头");
}
public static void main(String[] args) {
Dog dog = new Dog();
dog.makeSound();
dog.eat();
}
}
package com.abs;
public class Cat extends Animal{
@Override
public void eat() {
System.out.println("我是一只猫我会吃老鼠");
}
@Override
public void makeSound() {
System.out.println("我是一只猫,我会喵喵喵");
}
public static void main(String[] args) {
Cat cat = new Cat();
cat.eat();
cat.makeSound();
}
}
- 但反过来看,Animal类中的两个方法方法体中的内容就可以不用写了,因为,每个动物子类都有自己的客体化差异,都需要将这些方法进行重写,这时候我们就可以使用abstract修饰符将Animal类修饰为抽象类,将Animal类中的方法,修饰为抽象方法,如下方代码所示:
package com.abs;
public abstract class Animal {
public abstract void eat();
public abstract void makeSound();
}
- 这时候我们再运行发现,任然可以运行,且animal类逻辑更加清晰,且更加清爽了。
概念
- 抽象类以及抽象方法其目的在于,给子类指定实现的规则,并要求子类对其进行完善
- 抽象类方法可以强制让子类通过重写实现父类的方法,除非子类也是抽象类

- 抽象类中可以存在普通方法,子类可以直接继承到使用
- 抽象类存在构造方法,子类可以通过super()访问
- 抽象类的子类,要么重写抽象类中的所有抽象方法,要么是抽象类
- 抽象类其本身不能被示例化,因为抽象类中的抽象方法没法被调用,实例化没有意义
abstract关键字冲突的问题
- final:被 abstract 修饰的方法,强制要求子类重写,被 final 修饰的方法子类不能重写
- private:被 abstract 修饰的方法,强制要求子类重写,被 private 修饰的方法子类不能重写
- static:被 static 修饰的方法可以类名调用,类名调用抽象方法没有意义