关于抽象类,你想知道的这里都有(maybe)——Java中的抽象类浅析

本文详细阐述了抽象类和抽象方法在Java中的概念,如何通过abstract关键字定义,以及它们在继承关系中的应用。重点讲解了抽象类的特性、抽象方法的使用场景和子类的覆写规则。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

抽象类和抽象方法

当我们定义一个类时,常常需要定义一些方法来描述该类的行为特征,但有时这些方法的实现方式是无法确定的。比如,我们定义一个Animal类时,在里面定义一个say()方法用来表示动物的叫声,我们有很多动物子类继承了Animal这个父类,但是不同的动物叫声也是不同的。

因此我们无法在Animal中准确的描述,我们需要将这个say()方法定义成抽象方法,意思就是多种动物都有这种方法,我们用abstract关键字来修饰,并且在定义方法时不需要实现方法体。当一个类中包含了抽象方法,那么该类也必须使用abstract关键字修饰,这种类就叫做抽象类。抽象方法所在的类必须是抽象类,但是,抽象类中不一定要有抽象方法
现实生活中有很多的抽象类,这些类都是概念化的,没法具体到某个实例,描述这一类对象共同的属性和行为称之为抽象,比如 人类就是一个抽象类,因为中国人,日本人,美国人都是人类,他们都是人类这个类的子类。

  • Java中定义抽象类或者抽象方法使用abstract关键字。
  1. 抽象方法所在的类必须使用abstract关键字声明为抽象类。
  2. 抽象类是普通类的超集,普通类有的,抽象类都有,只是比普通类多了一些抽象方法而已。
  3. 抽象方法所在的类必须是抽象类,子类(普通类)若继承了抽象类,必须覆写所有父类的抽象方法。如果子类是是一个抽象类,那么不需要覆写所有的抽象方法。
  4. 抽象方法指的是使用abstract关键字声明,只有函数声明,没有函数实现的方法,称为抽象方法。
public abstract class Animal {
    //没有方法体,子类覆写的时候实现该方法。
	public abstract void say();
}
  1. 本地方法也没有方法体,但不是抽象方法,这个方法的具体实现是由JVM实现的。
  2. 若一个类使用abstract声明为抽象类,无法直接通过该类实例化对象,哪怕该类中一个抽象方法都没有。当一个类是抽象类,不管他有没有抽象方法,这个类本身就是一个抽象的概念,没法具体到某个特定的实例。只能通过子类向上转型变为抽象父类的引用。
		Animal ani1 = new Dog();
  1. 子类继承了抽象类,就必须强制子类(普通类)覆写抽象类中的所有抽象方法,包括继承来的抽象方法,也满足单继承局限,一个子类只能继承一个抽象类。
abstract class Animal {
	abstract void say();
	abstract void run();
}
//Dog类是抽象类,可以选择性覆写父类的抽象方法。
abstract class Dog extends Animal {
//此时我们就没有覆写,我们是重新定义了一个抽象方法
	abstract void swim();
//也可以都覆写,如果此时都覆写了,那么Dog的子类就不用再继续覆写,只需要覆写Dog类的抽像方法即可
	// void say();
	// void run();
}
public class ChaiQuan extends Dog {
//此时的子类就需要覆写所有父类的抽象方法
	void say(){}
	void swim(){}
	void run() {}
}
  1. 抽象类虽然没办法直接实例化对象,但是也可以存在构造方法,子类仍然满足 is a关系,子类和抽象父类之间仍然满足“继承树”关系。子类在实例化对象的时候,仍然遵从继承的原则,先调用父类(抽象类)的构造方法,再调用子类的构造方法!
public class Fun extends BaseTest {
	private int num = 10;
	//覆写父类的抽象方法
	void print() {
	System.out.println("num=" + num);
	}
	public static void main(String[] args) {
	//newFun的时候先在子类的无参构造首行默认调用父类的无参构造
	new Fun();
	}
}
abstract class BaseTest {
	public BaseTest() {
		this.print();
	}
	abstract void print();
}

执行结果如下:

在这里插入图片描述
为什么是0呢,因为在Fun继承了BaseTest,产生子类对象时调用的是子类的构造方法,此时子类构造方法的首行会默认先调用父类的无参构造,父类的无参构造中调用了print方法,此时的print方法已经被子类覆写过,所以表现出来的方法就是子类覆写后的方法,此时的num还没有被赋值,所以是0!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值