📢 文章提示

  1. 适用于已经掌握Java基础语法的学习者

  2. 通过具体代码案例理解抽象类与接口的区别

  3. 包含Java 8+接口新特性说明

  4. 提供开发中"什么时候用抽象类/接口"的决策指南


🌟 前言

在Java面向对象编程中,抽象类和接口是构建程序骨架的二大基石。很多新手容易混淆这些概念,本文将通过代码实战,带你彻底掌握它们的区别与应用场景,让你的代码设计更专业!


一、抽象类:半成品模板

1、abstract修饰类或者方法,其中抽象类不能实例化,抽象方法不能有具体实现。

2、抽象类的主要特点:有抽象方法的类必须是抽象类,抽象类不能创建对象,仅作为一种特殊的父类,让子类继承并实现

3、一个类继承抽象类,必须重写完抽象类的全部抽象方法,否则这个类也必须定义为抽象类。

public abstract class A {//抽象的本质是不能有对象,抽象类的基本作用就是被继承
    private String name;//抽象类有成员变量
    public A(){
        System.out.println("抽象类A的构造方法");
    }//抽象类有构造方法
    public void show(){
        System.out.println("抽象类A的show方法");
    }//抽象类的方法可以有方法体
//抽象方法,抽象类中可以有没有抽象方法,抽象方法没有方法体,只有方法声明,子类必须重写抽象方法
    public abstract void show();//抽象类的抽象方法不能写方法体
}

4、抽象类的应用场景:父类的每个子类的行为不同,但父类只定义了行为,子类必须实现,所以用抽象类,抽象类是为了更好的支持多态。

抽象类简化了需要重写的父类方法的代码,更加便于调用子类时多态的实现,更具解耦性。

5、模板方法设计模式:提供了方法作为完成某类操作的模板,模板方法封装了每个实现步骤,允许子类实现特定步骤的实现。

模板方法是给子类直接使用的,不能被子类重写,一旦子类重写了模板方法,模板方法就失效了。

public abstract class fu {//父类抽象类
    public final void show(){//模板方法不能被重写
        System.out.println("模板方法");//子类共同的部分
        show1();//子类不同的部分
    }
    public abstract void show1();//抽象方法,子类一定要重写,不然就报错,这样做是最佳实现
}
public class A extends fu {//子类
    @Override
    public void show1(){System.out.println("A show1方法");}
}
public class B extends fu {//子类
    @Override
    public void show1(){System.out.println("B show1方法");}
}

二、接口:行业标准协议

1、interface:

传统接口(内部只能写常量和抽象方法/jdk8以前),默认方法,私有方法,静态方法(新增方法形式)

实现类实现多个接口,必须重新写完全部接口的全部抽象方法,否则这个类必须定义成抽象类

public interface A {//接口不能创建对象,只能被实现
//JDK-8之前,接口只能定义常量和抽象方法,不能定义具体方法。
//1、常量:接口中的常量默认是public static final的,所以可以省略。
    String NAME="rasion";

    //2、抽象方法:接口中的抽象方法默认是public abstract的,所以可以省略。
//    public abstract void show();
    void show();
}
public class C extends D implements A,B {//实现接口的类,可以实现多个接口,但只能实现一个抽象类
    @Override
    public void show() {
        System.out.println("C实现A\B接口的show方法");
    }
}

 新增的方法增强接口能力,便于项目扩展与维护(若新增方法,可以直接写在接口中,不用修改实现类,更方便扩展)

    //jdk-8之后的三种方法
    //a、默认方法,一定要加default修饰符,默认会用public修饰,用接口的实现类对象调用
    default void defaultMethod(){
        System.out.println("defaultMethod");
        privateMethod();
    }

    //b、静态方法,一定要加static修饰符,默认会用public修饰,只能用当前接口名
    static void staticMethod(){//静态方法
        System.out.println("staticMethod");
    }

    //c、私有方法,一定要加private修饰符,默认会用private修饰,用接口中的其他实例方法调用
    private void privateMethod(){//私有方法
        System.out.println("privateMethod");
    }
2、接口的好处:

弥补了类单继承的不足,可以实现多接口,使类的角色更多,功能更加强大(接口可以是一种属性)。

让程序可以面向接口编程,更利于程序的解耦合。

public class test {
    public static void main(){
//        Driver d=new Teacher();//做接口解耦合,可以不改变自己本来的代码
        Driver d=new Student();
        Cook c=new Student();
    }
}
public interface Driver {}
public interface Cook {}
class people{}//抽象类
class Teacher extends people implements Driver,Cook{}//实现多个接口,用逗号隔开
class Student extends people implements Driver,Cook{}
3、注意事项:

(1)、接口与接口可以多继承,一个接口可以同时继承多个接口,但接口不能继承类。

[!注意]

类与类:单继承,一个类只能有一个父类

类与接口:多继承,一个类可以同时实现多个接口

// 游泳能力协议
interface Swimmable {
    void swim();
}

// 飞行能力协议  
interface Flyable {
    void fly();
}

// 鸭子实现多个协议
class Duck implements Swimmable, Flyable {
    @Override
    public void swim() {
        System.out.println("划水前进");
    }
    
    @Override
    public void fly() {
        System.out.println("扑腾翅膀飞行");
    }
}

(2)、一个接口可以继承多个接口,若多个接口中出现方法签名冲突,此时不支持多继承,也不支持多实现(即两个接口都有同一个方法名,但是方法签名不同,即方法类型不同,则报错)。

(3)、一类继承父类,同时又实现接口,若父类与接口中有同名的方法,则会优先实现父类的方法。(若想调用接口的们只能新建中专方法,接口名.super.方法名)

(4)、一个类实现多个接口,如果多个接口中存在同名的默认方法,要想不冲突,这个类重写该方法即可。

4、抽象类与接口区别:
相同点:

(1)、都是抽象的,不能创建对象,都只能被继承,都可以有抽象方法。

(2)、继承抽象类或者实现接口,都必须重写抽象方法。

(3) 、都能支持多态,都能实现解耦合。

不同点:

(1)、抽象类中可以定义类的全部普通成员,接口只能定义常量、抽象方法,以及三种方式。

(2)、抽象类只能被类单继承,但是接口可以被类多继承(还可以继承其他类与其他接口)。

(3)、抽象类体现模板思想,更利于做父类的,实现代码的复用性;接口更适合做功能的解耦合,解耦合更加灵活。(最佳实现)

特性 抽象类 接口
方法实现 可以有具体方法 Java8+支持默认方法
变量类型 任意类型 默认public static final
继承机制 单继承 多实现
构造方法
设计理念 "是什么"的层级关系 "能做什么"的能力声明

 核心要点总结:

// 案例:游戏角色设计
abstract class Character {  // 抽象类:基础模板
    protected int hp;
    
    abstract void attack();  // 必须实现的攻击方式
    
    void takeDamage(int damage) {  // 通用方法
        hp -= damage;
        System.out.println("剩余HP:" + hp);
    }
}

interface MagicSkill {       // 接口:扩展能力
    void castSpell();
}

class Mage extends Character implements MagicSkill {
    @Override
    void attack() {
        System.out.println("法杖普通攻击!");
    }
    
    @Override
    public void castSpell() {
        System.out.println("火球术!");
    }
}

新手常见误区

  1. 误区:接口比抽象类高级
    正解:两者是互补关系,不是替代关系

  2. 误区:接口方法必须全部实现
    正解:如果类不是抽象的,必须实现所有方法。但可以通过适配器模式部分实现

  3. 误区:抽象类不能有构造方法
    正解:可以有构造方法,用于初始化抽象类的状态


🚀 文章总结

掌握抽象类和接口的关系,就像学会了编程世界的"搭积木"技巧。记住:

  • 抽象类是 "半成品模板" → 就像乐高的基础底板

  • 接口是 "能力证书" → 就像各种形状的拼接接口

当你在设计程序时:

  1. 先思考对象间的关系(继承→抽象类)

  2. 再考虑需要的能力扩展(实现→接口)

  3. 最后用修饰符控制访问权限

记住,好的设计=正确的抽象+清晰的接口,就像用积木搭建城堡,既要稳固的基础,也要灵活的扩展!

Logo

脑启社区是一个专注类脑智能领域的开发者社区。欢迎加入社区,共建类脑智能生态。社区为开发者提供了丰富的开源类脑工具软件、类脑算法模型及数据集、类脑知识库、类脑技术培训课程以及类脑应用案例等资源。

更多推荐