抽象类和接口区别

2021/08/13 Java基础 共 2813 字,约 9 分钟

在我们的日常开发汇中,抽象类和接口是高频使用的,它们之间的区别也是面试必考点,下面我们来具体分析这两者有什么区别。

抽象类

  • 抽象类,用来表示一个抽象概念.
  • 是一种只能定义类型,而不能产生对象的类,所以定义了抽象类则必须有子类的出现.
  • 抽象类的好处在于能够明确地定义子类需要覆写的方法
  • 抽象类需要使用abstract声明.
  • 抽象类里可以有抽象方法,该方法特征在于:只有声明,没有实现。

以下举例说明:

抽象父类
/**
 * 抽象类不能实例化
 */
public abstract class AbstractAnimal {

    // protected属性,子类可以继承
    protected int age = 0;

    // 私有属性
    private String name;

    // 构造器1
    public AbstractAnimal(String name) {
        this.name = name;
    }

    // 构造器2
    public AbstractAnimal(int age, String name) {
        this.age = age;
        this.name = name;
    }

    // 非抽象方法已实现,子类无需实现或者可以重写
    public void eat() {
        System.out.println("animal eat");
    }

    // 抽象方法, 非抽象子类必须实现
    public abstract void sleep();

    // static方法,子类可以继承
    public static void breath() {
        System.out.println("animal breath");
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

子类(非抽象)
/**
 * 继承
 */
public class Dog extends AbstractAnimal {

    public Dog(String name) {
        super(name);
    }

    // 必须实现抽象方法 
    @Override
    public void sleep() {
        System.out.println("dog sleep");
    }

    // 默认继承父类实现,也可以重写方法
//    public void eat() {
//        System.out.println("dog eat");
//    }

    public static void main(String[] args) {
        Dog dog = new Dog("wang_cai");
        dog.eat();
        System.out.println("dog age:" + dog.age);

    }
}

子类(抽象)
// 抽象子类
public abstract class AbstractDog extends AbstractAnimal {

    public AbstractDog(String name) {
        super(name);
    }

    public AbstractDog(int age, String name) {
        super(age, name);
    }

    // 抽象子类, 可以实现父类的抽象方法, 也可以不实现
//    @Override
//    public void sleep() {
//        System.out.println("AbstractDog sleep");
//    }

    // 抽象方法, 非抽象子类必须实现
    public abstract void happy();


}

接口

接口(英文:Interface),在JAVA编程语言中是一个抽象类型,是抽象方法的集合,接口通常以interface来声明。一个类通过继承接口的方式,从而来继承接口的抽象方法。

接口的最大特点是包含抽象的方法,实现类必须实现这些方法。

以下举例说明:

接口(底层接口)

jdk1.8后增加了default方法,接口可以自己实现default方法,实现类可以不用实现或可以重写该方法,和抽象类的非抽象方法相似。

定义的属性是全局静态变量,不能被private和protected修饰。

/**
 * 接口
 */
public interface AnimalBehavior {

    // 属性默认是public且static且final, 接口的全局属性
    int age = 0;

    // 默认是public修饰
    void eat();

    // default修改, 默认实现方法, 实现类不用实现该方法
    default void sleep(){
        System.out.println("animal sleep");
    }
}
实现类
public class DogBehavior implements AnimalBehavior {

    // 必须实现该方法
    @Override
    public void eat() {
        System.out.println("dog eat");
    }

    // 默认不用实现default方法, 也可以重写
//    @Override
//    public void sleep() {
//        System.out.println("dog sleep");
//    }

    public static void main(String[] args) {
        DogBehavior dogBehavior = new DogBehavior();
        dogBehavior.eat();
        dogBehavior.sleep();
        System.out.println("dog.age=" + age);
    }
}

// 运行结果
dog eat
animal sleep
dog.age=0
子接口(继承底层接口)
/**
 * 接口
 */
public interface TwoLegsAnimalBehavior extends AnimalBehavior {

    void run();

}
实现类(实现子接口)
public class DuckBehavior implements TwoLegsAnimalBehavior {

    // 实现的是继承AnimalBehavior的接口
    @Override
    public void eat() {
        System.out.println("duck eat");
    }

    // 实现的是上层接口
    @Override
    public void run() {
        System.out.println("duck two legs run");
    }

    // 默认不用实现default方法, 也可以重写
//    @Override
//    public void sleep() {
//
//    }
}

区别

相同点:都是抽象的,都可以有实现方法(前提jdk1.8)(继承或实现类可以不用实现,也可以重写方法),都可以被继承。

最大不同:一个类只能继承一个抽象类(is-a),但可以实现多个接口(has-a),抽象类的属性可以私有,接口的属性只能是public且static且final,全局静态不可变属性。

接口方法和属性都是public,而抽象类可以私有;

接口是可以多继承,但是抽象类只能单一继承;

抽象类可以实现接口;

使用场景

如果需要多继承,使用接口;

模板方法设计模式是抽象类的典型应用;

抽象类主要是代码的复用,表示is-a关系;

接口主要是一种协议约定,上游不用关心底层实现。

文档信息

搜索

    Table of Contents