Java中的抽象类与接口

目录

一、抽象类

[1.1 抽象方法](#1.1 抽象方法)

[1.2 抽象类的定义](#1.2 抽象类的定义)

二、接口

[2.1 接口的定义](#2.1 接口的定义)

[2.2 接口的使用](#2.2 接口的使用)

[2.3 接口与抽象类的异同](#2.3 接口与抽象类的异同)

[2.3.1 相同点](#2.3.1 相同点)

[2.3.2 不同点](#2.3.2 不同点)


一、抽象类

1.1 抽象方法

当一个方法只有方法的声明,没有方法的实现时,这个方法就只能被 abstract 关键字修改。而被 abstract 关键字修饰的方法就叫抽象方法。

java 复制代码
abstract class Father {
    String name;

    public abstract void sayHi();
}
class Son extends Father {
    public Son() {

    }
    public Son(String name) {
        this.name = name;
    }
    public void sayHi() {
        System.out.println(name);
    }
}

public class FinalDemo {
    public static void main(String[] args) {
        Son son = new Son("小华");
        son.sayHi();
    }
}

当父类中声明的方法,但又不确定子类如何去实现这个方法时,就需要将父类中的方法定义为抽象方法。此时,父类中的这个抽象方法就是一种约定,或者叫规则。

1.2 抽象类的定义

一个类如果被 abstract 关键字修饰,那么这个类就叫抽象类。抽象类必须有子类,因为抽象类不能直接实例化。

java 复制代码
abstract class Father {
    String name;

    public abstract void sayHi();
    public abstract void sayBye();
}
abstract class Son extends Father {
    public Son() {

    }
    public Son(String name) {
        this.name = name;
    }
   /* public void sayBye() {

    }*/
    public void sayHi() {
        System.out.println(name);
    }
}

如果某个子类继承了抽象类,那么它必须实现抽象类中的所有抽象方法,如果没有实现所有的抽象方法,那么它也只能是抽象类。

注意:因为被final修饰的类必须不能被继承,而被abstract关键字修饰的类必须有子类。所以它们两个不能同时使用。即抽象类不能被final修饰。

二、接口

2.1 接口的定义

如果一个抽象类中所有的方法都是抽象方法,那么这个类就无需定义成抽象类,而是定义为接口。

在 JDK1.8 之前,接口中只能声明抽象方法,而在 JDK1.8 中定义默认方法和静态方法,这两种方法都是实现了的。如果定义为接口,那么需要使用 interface 关键字来进行修饰。例如:

java 复制代码
public interface InterfaceDemo {
    public static final String company = "open";
    public abstract void say();
    public abstract void show();
    public abstract int getAge();
}

2.2 接口的使用

在上面的接口,所有的方法都是抽象方法。对接口而言,由于都是抽象方法,因此,对象 public abstrace 关键字是可以省略。

java 复制代码
public interface InterfaceDemo {
    String company = "open";
    void say();
    void show();
    int getAge();
}

接口中的方法都是抽象的,公共的方法;接口的属性都是静态常量。

在 JDK1.8中,定义默认方法和静态方法。默认方法是使用 defalut 关键字来修饰的,而静态方法是使用 static 关键字来修饰的。

java 复制代码
public interface InterfaceDemo {
    String company = "open";
    void say();
    void show();
    int getAge();

    default void run() {
        System.out.println("run() 方法,它是一个默认方法");
    }

    static String print(String str) {
        return str.toUpperCase();
    }
}

接口定义后,不能直接实例化,需要有子类,子类通过implements关键字来实现接口。

java 复制代码
public class InterADemo implements InterA {
    @Override
    public void say() {
        System.out.println("say()");
    }

    @Override
    public void show() {
        System.out.println("show()");
    }

    @Override
    public int getAge() {
        return 18;
    }

    public static void main(String[] args) {
        InterADemo id = new InterADemo();
        id.say();
        id.show();
        System.out.println(id.getAge());
        id.run();
    }
}

2.3 接口与抽象类的异同

2.3.1 相同点

  1. 接口和抽象类都不能直接实例化,都需要有子类

  2. 它们都是多态前提,多态前提是要么继承,要么实现,另一个就是要重写

2.3.2 不同点

  1. 抽象类是使用 abstract 关键字来修饰,而接口是使用 interface 关键字来修饰

  2. 抽象类子类使用 extends 来继承,而接口的子类是使用 implements 来实现

  3. 抽象类中是可以有抽象方法也可以没有抽象方法,但接口中不能有非抽象方法

  4. 抽象类中可以有构造方法,而接口中是没有构造方法的

  5. 抽象类中的属性可以不是常量,而接口中所有属性都是常量

  6. 子类只能继承一个父类,但是可以实现多个接口。如果一个类既要继承又要实现,那么是先继承后实现

例如:

java 复制代码
abstract class AbsTest {
    private String name;
    public final int age = 18;

    public AbsTest() {

    }
    public AbsTest(String name) {
        this.name = name;
    }

}

interface InterB {
    String name = "张三";
    // 在接口中不允许有构造方法
    /*public InterB() {

    }*/
}

interface InterC {

}

interface InterD extends InterC {
    
}

public class AbstractDemo extends AbsTest implements InterB, InterC {
}

在上面的例子中我们知道,接口与接口也可以通过extends进行继承。

注意:

在接口中是支持多继承的

java 复制代码
interface InterB {
String name = "张三";
// 在接口中不允许有构造方法
/*public InterB() {

}*/
}

interface InterC {

}

interface InterD extends InterC, InterB {

}

这是为什么呢?

1)对于普通的类:

java 复制代码
// Java中为什么不支持多继承
class ClassA {
public void show() {
  System.out.println("ClassA.show");
}
}
class ClassB {
public void show() {
  System.out.println("ClassB.show");
}
}
public class ExtendsDemo extends ClassA, ClassB {
public static void main(String[] args) {
  ExtendsDemo ed = new ExtendsDemo();
  ed.show();
}
}

由于JVM不知道调用show()方法时执行的是哪个类中的,所以Java避免这种不确定因素,不支持多继承。

2)在接口中;

java 复制代码
// 接口支持多继承
interface InterAA {
void show();
}
interface InterBB {
void show();
}

interface InterCC extends InterAA, InterBB {
void show();
}

public class ExtendsDemo2 implements InterCC  {
@Override
public void show() {
  System.out.println("ExtendsDemo2.show");
}
}

在接口中支持多继承的原因是:接口中的方法只是声明没有实现,也就是说,在接口中只是定义一种规范,具体的实现在子类中完成。所以就不存在不确定的因素,所以支持多继承 。

相关推荐
腻害兔1 小时前
【若依项目-产品经理视角】RuoYi-Vue-Pro 源码拆解:字典、短信、邮件、通知——后台系统的“基础设施四件套“!
java·前端·vue.js·产品经理·ai编程
SeaTunnel1 小时前
从 Python Script 地狱到标准化数据集成框架
大数据·开发语言·python·程序员·代码·seatunnel
碎光拾影2 小时前
ARM交叉工具链各工具作用及IMX6ULL平台LED+蜂鸣器裸机程序实现
java·开发语言·数据库
Marst Code2 小时前
(python)2026Plotly 库评估:交互式可视化到底值不值得引入?
开发语言·python
Miao121313 小时前
微服务 API 测试实践:海外某民宿平台如何构建模式驱动测试基础设施
java·开发语言
腻害兔3 小时前
【若依项目-产品经理视角】RuoYi-Vue-Pro 源码拆解:支付模块 yudao-module-pay,一个让产品经理都看懂的支付中台设计
java·前端·vue.js·产品经理·ai编程
CRMEB系统商城4 小时前
开源自建还是SaaS订阅?算一笔3年经济账
java·大数据·开发语言·开源
keyipatience5 小时前
线程栈与TLS和线程互斥
java·linux·服务器·开发语言·ubuntu
我的xiaodoujiao5 小时前
快速学习Python基础知识详细图文教程9--函数进阶
开发语言·python·学习·测试工具
weixin_408099675 小时前
2026 图片去水印 API 接口完全指南:一键去除图片水印(附 Python/Java/PHP/C# 示例)
java·python·php·图片处理·api调用·图片去水印·石榴智能