Java抽象类和接口的详细区别(全)

简介: 这两者经常在笔试以及面试中经常问及,甚至在项目实战中还在纠结用哪一种类型今天就此问题详细剖析一下以往我的文章中也有稍微提及:java框架零基础从入门到精通的学习路线(超全)此处将其这些文章抽离公共部分,详细总结下这两概念此处的总结偏向于两者概念的总结,将其制作成表格抽象类是半抽象的,有构造方法,只允许出现常量和抽象方法。类和类之间只能单继承,一个抽象类只能继承一个类(单继承)。接口是完全抽象的,没有构造方法,接口和接口之间支持多继承,一个类可以同时实现多个接口比较内容抽象类。

前言

这两者经常在笔试以及面试中经常问及,甚至在项目实战中还在纠结用哪一种类型
今天就此问题详细剖析一下

以往我的文章中也有稍微提及: java框架零基础从入门到精通的学习路线(超全)

此处将其这些文章抽离公共部分,详细总结下这两概念

1. 抽象类

抽象类是类和类之间的共同特征,将这些共同特征进一步形成抽象类,由于类本身不存在,所以抽象类无法创建对象。
类到对象是实例化,对象到类是抽象
抽象方法不能被 final 修饰,因为抽象方法就是被子类实现的

  • 采用 abstract 关键字定义的类就是抽象类,采用 abstract 关键字定义的方法就

是抽象方法

  • 抽象的方法只需在抽象类中,提供声明,不需要实现
  • 如果一个类中含有抽象方法,那么这个类必须定义成抽象类。抽象类中不一定有抽象方法,抽象方法必须出现在抽象类中
  • final和abstract不能同时同时使用,这两个关键字是对立的
  • 抽象类的子类可以是抽象类。也可以是非抽象类
  • ==一个非抽象的类,继承抽象类,必须将抽象类中的抽象方法进行覆盖/重写/实现==

==抽象类无法实例化,无法创建对象,抽象类是被子类来继承的==
抽象类可以有抽象类的子类

public class AbstractTest01 {
    public static void main(String[] args) {
        new a();//错误,不可创建对象
    }
}
//定义一个抽象类
abstract  class a{
    
}
//不是抽象类可以继承抽象类并且实例化
class b extends a{
}

//抽象子类可以继承抽象类
abstract class c extends a{
}

==抽象类无法实例化,但抽象类有构造函数可以供子类使用==
如果抽象类定义了有参构造函数而没有无参构造函数,子类定义找不到无参构造函数会出错,抽象类无法实例化调用对象(new对象),但是有构造函数可以给子类使用

abstract  class a{
    
}

class b extends a{
    public b(){
        super();
    }
}

==抽象方法表示没有实现的方法,没有方法体的方法==

  • 没有方法体,以分号结尾
  • 前面的修饰符列表中有abstract关键字

比如public abstract void dosome();

但是java语言中凡是没有方法体的方法都是抽象方法(×)
因为Object类中就有很多方法都没有方法体,都是以“;”结尾的,但他们都不是抽象方法

public class AbstractTest03 {
    public static void main(String[] args) {
//此时不能再 new Employee 了
        Person p = new Employee();
    } }
abstract class Person {
    private String name;
    public void setName(String name) {
        this.name = name;
    }
    public String getName() {
        return name;
    }
    //此方法各个子类都可以使用
    public void commonMethod1() {
        System.out.println("---------commonMethod1-------");
    }
    //采用 abstract 定义抽象方法
    public abstract void printInfo();
}
abstract class Employee extends Person {
    //再次声明该方法为抽象的
    public abstract void printInfo();
}
class Student extends Person {
    //实现抽象的方法
    public void printInfo() {
        System.out.println("Student.printInfo()");
    } 
    }

2. 接口

接口是特殊的抽象类,类与类是继承extends,类与接口是实现implements,其实都是继承

  • 接口是一种“引用数据类型”,完全抽象的,支持多继承,且一个接口可以继承多个接口,只有常量+抽象方法
  • 所有的元素都是public修饰的,抽象方法的public abstract可以省略,常量的public static final可以省略,方法不能有方法体

定义的格式

[修饰符列表] interface 接口名{}

==支持多继承,且一个接口可以继承多个接口==
每一个interface 都会生成一个class后缀名的文件

public class text1 {
    public static void main(String[] args) {
    }
}

interface a{
}

interface b extends a{
}

interface c extends a,b{
}

==接口中的方法是抽象,所以不能有方法体==
==定义抽象方法的时候可以省略修饰符public abstract==

interface a{
    int sum(int a,intb);//可以省略,默认系统会给你加上
    void dosome();//可以执行通过
    void dosome(){};//不可以执行通过,不能有方法体
}

==常量的定义结合final 是public static final可以省路==

public class text1 {
    public static void main(String[] args) {
        //定义输出的时候 需要用类名加变量 也就是a.i
        //而且不允许在修改常量
    }
}
interface a{
    public static final int i=100;
    int z=1;//z也是一个常量而不是变量 不能修改
}

3. 两者结合

==当一个非抽象的类实现接口的话,必须将接口中所有的抽象方法全部实现(覆盖、重写)==

// 特殊的抽象类,完全抽象的,叫做接口。
interface MyMath{
    double PI = 3.1415926;
    int sum(int a, int b);
    int sub(int a, int b);
}

// 这样没问题
abstract class MyMathImpl implements MyMath {
}

//编译出错
class MyMathImpl implements MyMath {
}

//添加方法重写实现
//修正
class MyMathImpl implements MyMath {

    //错误:正在尝试分配更低的访问权限; 以前为public
    /*
    int sum(int a, int b){
        return a + b;
    }
    */

    // 重写/覆盖/实现 接口中的方法(通常叫做实现。)
    public int sum(int a, int b){
        return a + b;
    }

    public int sub(int a, int b){
        return a - b;
    }
}

接口中的方法必须是public :
如果删除执行不通过,因为接口是public,如果继承后,不写public执行后是分配更低的权限这是不行的,所以要添加public

==结合多态面向接口编程==

public class Test02{
    public static void main(String[] args){
        //错误: MyMath是抽象的; 无法实例化
        //new MyMath();

        // 父类型的引用指向子类型的对象
        MyMath mm = new MyMathImpl();
        // 调用接口里面的方法(面向接口编程。)
        int result1 = mm.sum(10, 20);
        System.out.println(result1);

        int result2 = mm.sub(20, 10);
        System.out.println(result2);
    }
}

==接口与接口之间可以多继承,一个类也可以多个接口==

interface X{
}
interface Y{
}
interface Z extends X,Y{ //接口和接口支持多继承。
}

一个类可以实现多个接口
java中类和类只支持单继承。实际上单继承是为了简单而出现的,java中的接口弥补了单继承带来的缺陷

interface A{
    void m1();
}

interface B{
    void m2();
}

interface C{
    void m3();
}

// 实现多个接口,其实就类似于多继承。
class D implements A,B,C{
    // 实现A接口的m1()
    public void m1(){
        
    }
    // 实现B接口中的m2()
    public void m2(){
        System.out.println("m2 ....");
    }
    // 实现接口C中的m3()
    public void m3(){
    
    }
}

==强转类型的时候,需要有继承关系才可==

A a = new D();
//a.m2(); // 编译报错。A接口中没有m2()方法。
B b = new D();
C c = new D();

// 这个编译没问题,运行也没问题。
// 调用其他接口中的方法,你需要转型(接口转型。)
B b2 = (B)a;
b2.m2();

// 直接向下转型为D可以吗?可以
D d = (D)a;
d.m2();

但如果没有继承关系不能强转

M m = new E();

// 经过测试:接口和接口之间在进行强制类型转换的时候,没有继承关系,也可以强转。
// 但是一定要注意,运行时可能会出现ClassCastException异常。
// 编译没问题,运行有问题。
K k = (K)m;

if(m instanceof K){
K k = (K)m;

interface K{
}

interface M{
}

class E implements M{
}

==继承和实现同时存在==
extends在前 implements在后

public class Test04{
    public static void main(String[] args){
        // 创建对象(表面看Animal类没起作用!)
        Flyable f = new Cat(); //多态。
        f.fly();
    }
}

// 动物类:父类
class Animal{
}


interface Flyable{
    void fly();
}

// 动物类子类:猫类
// Flyable是一个接口,是一对翅膀的接口,通过接口插到猫身上,让猫变的可以飞翔。
class Cat extends Animal implements Flyable{
    public void fly(){
        System.out.println("飞猫起飞,翱翔太空的一只猫,很神奇,我想做一只猫!!");
    }
}

4. 面试总结

此处的总结偏向于两者概念的总结,将其制作成表格

  • 抽象类是半抽象的,有构造方法,只允许出现常量和抽象方法。类和类之间只能单继承,一个抽象类只能继承一个类(单继承)。
  • 接口是完全抽象的,没有构造方法,接口和接口之间支持多继承,一个类可以同时实现多个接口
比较内容 抽象类 接口(特殊的抽象类)
构造方法 可以有 不可以有
方法 可以有抽象方法(抽象方法只能被abstract修饰,不可被private、static、synchronized和native修饰)和普通方法 只能有抽象方法,但1.8版本之后可以有默认方法。接口只有定义,不可有方法实现
实现 extend implments
类修饰符 public、default、protected 默认public
变量 可以有常量也可以有变量 只能是静态常量默认有public static final修饰,必须附上初始值,不能被修改
多继承 单继承 多个接口
静态方法 可以有 不可以

应用场景:

  • 关系密切:多个功能的集成部分,可用抽象类(抽象类提供简单方法)
  • 关系不密切:不相关的类提供公共部分,可用接口
相关文章
|
10天前
|
Java
java基础(4)public class 和class的区别及注意事项
本文讲解了Java中`public class`与`class`的区别和注意事项。一个Java源文件中只能有一个`public class`,并且`public class`的类名必须与文件名相同。此外,可以有多个非`public`类。每个类都可以包含一个`main`方法,作为程序的入口点。文章还强调了编译Java文件生成`.class`文件的过程,以及如何使用`java`命令运行编译后的类。
15 3
java基础(4)public class 和class的区别及注意事项
|
10天前
|
Java
java基础(12)抽象类以及抽象方法abstract以及ArrayList对象使用
本文介绍了Java中抽象类和抽象方法的使用,以及ArrayList的基本操作,包括添加、获取、删除元素和判断列表是否为空。
13 2
java基础(12)抽象类以及抽象方法abstract以及ArrayList对象使用
|
5天前
|
Java
java中面向过程和面向对象区别?
java中面向过程和面向对象区别?
15 4
|
9天前
|
Java
Java 抽象类详解
在 Java 中,抽象类是一种特殊类,用于提供基础定义并派生具体子类,支持代码复用。它包含抽象方法(无实现)和具体方法(有实现),不能被实例化,需用 `abstract` 关键字定义。子类必须实现所有抽象方法,除非子类也是抽象类。抽象类可用于定义模板或框架,确保子类实现特定方法。通过示例展示了如何定义抽象类 `Animal` 及其子类 `Dog` 和 `Cat`,并在主类中调用相关方法。使用抽象类可以提高代码复用性和设计质量,但也可能增加维护难度和性能开销。
ly~
|
8天前
|
安全 Java 大数据
php跟java有什么区别
PHP 和 Java 是两种常用编程语言,各有特色。PHP 语法简洁灵活,适用于快速开发中小型网站,尤其在 Web 脚本和数据库交互中表现出色。Java 则语法严谨,强类型特性使其在企业级应用、移动开发及大数据处理中更受欢迎,具备高稳定性和安全性。通过优化,PHP 性能可提升,而 Java 在大规模应用中表现更佳。总体而言,PHP 开发效率高但维护性稍差,Java 则更注重代码质量和安全性。
ly~
17 5
|
6天前
|
Java 测试技术
Java接口的生产环境应用注意点
在Java生产环境中,合理使用接口对提升代码质量至关重要。设计接口时应遵循单一职责原则,采用清晰命名,并控制方法数量。默认方法应谨慎使用,避免与实现类产生冲突。通过版本化管理接口更新,确保向后兼容。实现接口时需明确行为,保持实现与接口分离,利用多态增强灵活性。关注性能影响,适当文档注释及充分测试确保接口稳定可靠。综合运用这些策略,可以显著提高系统的可扩展性和维护性。
|
6天前
|
Java
Java 接口的简化理解
Java 接口是一种强大的概念,用于定义方法签名而非具体实现,作为行为规范,强调功能而非实现细节。接口是特殊的引用类型,包含常量和方法签名。其特点包括:无实现方法体、支持多重继承、内置常量定义。通过示例展示了如何定义和实现接口,以及如何通过接口引用调用实现类的方法。接口的应用场景包括抽象化、插件架构和松耦合设计。从 Java 8 起,接口还支持默认方法和静态方法,进一步增强了其灵活性和扩展性。理解接口是 Java 编程的基础之一。
|
15天前
|
Java 大数据 API
Java 流(Stream)、文件(File)和IO的区别
Java中的流(Stream)、文件(File)和输入/输出(I/O)是处理数据的关键概念。`File`类用于基本文件操作,如创建、删除和检查文件;流则提供了数据读写的抽象机制,适用于文件、内存和网络等多种数据源;I/O涵盖更广泛的输入输出操作,包括文件I/O、网络通信等,并支持异常处理和缓冲等功能。实际开发中,这三者常结合使用,以实现高效的数据处理。例如,`File`用于管理文件路径,`Stream`用于读写数据,I/O则处理复杂的输入输出需求。
|
7天前
|
Java
接口和抽象类【Java面向对象知识回顾②】
本文讨论了Java中抽象类和接口的概念与区别。抽象类是不能被实例化的类,可以包含抽象和非抽象方法,常用作其他类的基类。接口是一种纯抽象类型,只包含抽象方法和常量,不能被实例化,且实现接口的类必须实现接口中定义的所有方法。文章还比较了抽象类和接口在实现方式、方法类型、成员变量、构造方法和访问修饰符等方面的不同,并探讨了它们的使用场景。
接口和抽象类【Java面向对象知识回顾②】
|
14天前
|
Java
领略Lock接口的风采,通过实战演练,让你迅速掌握这门高深武艺,成为Java多线程领域的武林盟主
领略Lock接口的风采,通过实战演练,让你迅速掌握这门高深武艺,成为Java多线程领域的武林盟主
22 7
下一篇
无影云桌面