- 实现方式:实现接口的关键字为
implements,继承抽象类的关键字为extends。一个类可以实现多个接口,但一个类只能继承一个抽象类。所以,使用接口可以间接地实现多重继承。 - 方法方式:接口只有定义,不能有方法的实现;而抽象类可以有定义与实现,方法可在抽象类中实现。
- 访问修饰符:接口成员变量默认为
public static final,必须赋初值,不能被修改;接口中的抽象方法默认是public abstract;抽象方法被abstract修饰,不能被private、static、synchronized和native` 等修饰,必须以分号结尾,不带花括号。 - 变量:抽象类可以包含实例变量和静态变量,而接口只能包含常量(即静态常量)。
抽象类:
// 抽象类,用 abstract 修饰,不能 new 实例
abstract class BaseVoucher {
// 普通实例变量(抽象类可以有实例成员)
protected String name;
// 普通方法:有方法体,子类直接继承复用
public void printInfo() {
System.out.println("优惠券名称:" + name);
}
// 抽象方法:没有方法体,必须让子类重写,abstract关键字
public abstract void doSeckill();
}
// 子类继承抽象类,extends
class SeckillVoucher extends BaseVoucher{
// 必须重写父类的抽象方法
@Override
public void doSeckill() {
System.out.println("执行秒杀券业务逻辑");
}
}
public class TestAbstract {
public static void main(String[] args) {
// BaseVoucher base = new BaseVoucher(); // ❌ 抽象类不能实例化
BaseVoucher voucher = new SeckillVoucher(); // ✅向上转型,多态
voucher.doSeckill();
}
}
接口:
// 接口
interface IVoucher {
// 接口里的变量:默认 public static final,常量,必须初始化,不能修改
String TYPE = "优惠券";
// 抽象方法:默认 public abstract,没有方法体,实现类必须重写
void doSeckill();
}
// 实现类,implements,可以同时实现多个接口
class SeckillVoucherImpl implements IVoucher{
// 重写接口抽象方法
@Override
public void doSeckill() {
System.out.println("秒杀券实现逻辑");
}
}
public class TestInterface {
public static void main(String[] args) {
IVoucher voucher = new SeckillVoucherImpl(); // ✅向上转型,多态
voucher.doSeckill();
voucher.printType();
IVoucher.desc(); // 静态方法只能接口名调用
}
}
Question:抽象类能加 final 修饰吗?
不能,Java 中的抽象类是用来被继承的,而 final 修饰符用于禁止类被继承或方法被重写,因此,抽象类和 final 修饰符是互斥的,不能同时使用。
Question:抽象类可以被实例化吗?
不可以,不能用 new 关键词直接创建抽象类对象。抽象类的存在是为了被继承。抽象类可以有构造函数
Question:接口可以包含构造函数吗?
不可以有构造方法。
抽象类本质还是类,类都需要构造器;接口不是类,只是一套行为规范,没有实例,不需要构造期。