Java抽象类和接口(1)

news2024/11/28 18:47:58

🐵本篇文章将对抽象类接口相关知识进行讲解


一、抽象类

先来看下面的代码:

class Shape {
    public void draw() {
        System.out.println("画");
    }
}
class Cycle extends Shape {
    public void draw() {
        System.out.println("圆形");
    }
}
public class Test2 {
    public static void main(String[] args) {
        Shape shape = new Cycle(); 
        shape.draw();
    }
}

在上述代码中,Shape类中的draw方法,因为有动态绑定而始终没有被实现,且Shape类不能描绘某个具体的对象,我们可以将这样不能描绘某个具体对象的类设为抽象类,具体操作是:使用abstract关键字修饰这个类,此时这个类被称为抽象类,可以将抽象类中被重写的方法也用abstract修饰,此时这个方法就叫抽象方法,抽象方法不能有具体实现

abstract class Shape {
    public abstract void draw();
}
class Cycle extends Shape {
    public void draw() {
        System.out.println("圆形");
    }
}

二、抽象类相关总结

1. 抽象方法所在类必须是抽象类,抽象类不一定包含抽象方法

2. 抽象类中可以有和非抽象成员变量和成员方法(和普通类一样)

3. 抽象类不能被实例化

abstract class Shape {
    public abstract void draw();
}
class Cycle extends Shape {
    public void draw() {
        System.out.println("圆形");
    }
}
public class Test2 {
    public static void main(String[] args) {
        Shape shape = new Shape();
        //编译报错:抽象类不能被实例化
    }
}

4. 抽象类必须被继承,普通类继承抽象类后,必须重写抽象类中的抽象方法,(如果抽象类中没有抽象方法则可以不用重写)如果继承抽象类的也是抽象类则不用重写

5. 抽象方法不能被privatefinalstatic修饰

6. 在多层继承关系下,子类必须继承所有父类的抽象方法

abstract class A {
    public abstract void print();
}
abstract  class B extends A {
    public abstract void test();
}
class C extends B {
    //必须重写print和test方法,否则编译报错
    public void print() {
    }
    public void test() {
    }
}

7. 抽象类也有构造方法,只不过是被子类调用并帮助其初始化(因为抽象类不能实例化对象)

abstract class A {
    public abstract void print();
    public A() {
    }
}
class B extends A {
    public B() {
        super();
    }
    public void print() {
    }
}

三、接口

3.1 创建接口

创建一个接口需要用到interface关键字

interface 接口名 {

}

3.2 接口的使用

类和接口之间的关系是实现,即类实现接口,具体操作是使用implements关键字实现

类名 implements 接口名 {

}

下面举一个实例:

interface IUsb {
    void openDevice(); //默认为抽象方法
    void closeDevice();
}

class Mouse implements IUsb {
    public void openDevice() {
        System.out.println("打开鼠标");
    }

    public void closeDevice() {
        System.out.println("关闭鼠标");
    }

    public void clink() {
        System.out.println("点击鼠标");
    }
}

class Keyboard implements IUsb {
    @Override
    public void openDevice() {
        System.out.println("打开键盘");
    }

    @Override
    public void closeDevice() {
        System.out.println("关闭键盘");
    }

    public void inPut() {
        System.out.println("键盘输入");
    }
}


class Computer {
    public void powerOn() {
        System.out.println("开机");
    }
    public void powerOff() {
        System.out.println("关机");
    }

    public void useDevice(IUsb iUsb) {
        iUsb.openDevice(); //这里实现了多态

        if (iUsb instanceof Mouse) { //判断iUsb是否引用Mouse对象
            Mouse mouse = new Mouse(); //向下转型
            mouse.clink();
        } else if (iUsb instanceof Keyboard) {
            Keyboard keyboard = new Keyboard(); //向下转型
            keyboard.inPut();
        }
        iUsb.closeDevice();
    }
}

public class Test {
    public static void main(String[] args) {
        Computer computer = new Computer();

        computer.powerOn();
        computer.useDevice(new Mouse()); //向上转型
        computer.useDevice(new Keyboard()); //向上转型
        computer.powerOff();
    }
}

3.3 接口相关总结

1. 接口中定义的成员变量默认被public static final修饰,定义的成员方法默认被public abstract修饰

2. 接口中的方法如果没有具体实现则默认为抽象方法

3. 接口中的方法一般不能具体实现(没有方法块)如果要具体实现,应由defaultstatic修饰

interface IUsb {
    default void method() {
        System.out.println("实现method方法");
    }
    static void method1() {
        System.out.println("实现method1方法");
    }
}

4. 接口不能被实例化

interface IShape {
}
public class Test1 {
    public static void main(String[] args) {
        IShape iShape = new IShape();
        //编译报错:接口不能被实例化对象
    }
}

5. 一个类可以继承一个普通类/抽象类,同时还可以实现接口

interface A {
    
}
class B {

}
class C extends B implements A { //必须先继承在实现
}

6. 一个类实现一个接口后,必须重写其内部的方法

四、实现多接口

在Java中不支持多继承,但可以实现多接口,即一个类可以实现多个接口

class 类名 implements 接口名,接口名, ... {
}

实际上多接口就是为了解决Java中不能多继承的问题,下面举一个例子:

interface IRun {
    void run();
}

interface ISwim {
    void swim();
}

class Dog implements IRun, ISwim {
//实现这两个接口后,要重写接口中的抽象方法
    public void run() {
        System.out.println("跑");
    }
    
    public void swim() {
        System.out.println("游");
    }
}

将run()和swim()两个方法分别写到两个接口中而不是直接将这两个方法写到一个Animal类中让Dog类来继承的原因是:将来如果有其它类比如一个Bird类要继承Animal类,那就会直接将Animal类中所有的方法全部继承,但是“鸟不能游泳”所以这样写不符合逻辑

五、接口间的继承

Java中类和类之间不支持多继承,但接口和接口之间是支持多继承的

interface IJump {
    void jump();
}

interface ISing {
    void sing();
}

interface IRap extends IJump, ISing { }

class Student implements IRap{
    @Override
    public void jump() {}
    @Override
    public void sing() {}
}

接口间的继承的意义就是将多个接口合并为一个接口

六、Object类

object类是所有类的父类 

class Person {
    public String name;
    public Person(String name) {
        this.name = name;
    }
}

public static void main(String[] args) {

    public static void func(Object obj) { 
        System.out.println(obj); //这里会调用Object类中toString中的方法,打印obj所指对象的地址
    }


    public static void main(String[] args) {
        func(new Person("Sans")); //向上转型
    }    
}     

调用Object类中toString方法的源码顺序:

    public void println(Object x) { 
        String s = String.valueOf(x); //调用valueof方法
        synchronized (this) {
            print(s);
            newLine();
        }
    }

    public static String valueOf(Object obj) { 
        return (obj == null) ? "null" : obj.toString(); //若obj指向某个对象则调用toString方法
    }

    public String toString() {
        return getClass().getName() + "@" + Integer.toHexString(hashCode());
    }   //返回对象的地址

6.1 equals方法

equals方法是Object类中的成员方法,在此之前先来回顾一下“==”

如果==左右两侧是基本类型变量,比较的是变量中值是否相同
如果==左右两侧是引用类型变量,比较的是引用变量地址是否相同

equals的源码如下:

public boolean equals(Object obj) {
    return (this == obj);
}

下面举一个实例:

class Person {
    public String name;
    public Person(String name) {
        this.name = name;
    }
}

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

        func(new Person("Sans"));

        Person person1 = new Person("Sans");
        Person person2 = new Person("Sans");

        System.out.println(person1.equals(person2));
        //由于person1和person2指向不同对象,所以它们的地址不同
}

如果要使用equals方法比较对象的内容,则需要在Person类中重写equals方法,

class Person {
    public String name;
    public Person(String name) {
        this.name = name;
    }

    public boolean equals(Object obj) {
        Person per = (Person) obj;
        return per.name.equals(this.name); 
        //name是String类型,String类继承了object类同时也重写了equals方法
        //所以这里是调用了String类的方法
    }

}

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

        Person person1 = new Person("Sans");
        Person person2 = new Person("Sans");

        System.out.println(person1.equals(person2));
        //Person类继承了object类并重写了equals方法,所以这里
        //发生动态绑定,调用子类即Person类的equals方法
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1254190.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Leetcode—18.四数之和【中等】

2023每日刷题&#xff08;四十一&#xff09; Leetcode—18.四数之和 实现代码 class Solution { public:vector<vector<int>> fourSum(vector<int>& nums, int target) {vector<vector<int>> ans;sort(nums.begin(), nums.end());int n …

C/C++ 常用加密与解密算法

计算机安全和数据隐私是现代应用程序设计中至关重要的方面。为了确保数据的机密性和完整性&#xff0c;常常需要使用加密和解密算法。C是一种广泛使用的编程语言&#xff0c;提供了许多加密和解密算法的实现。本文将介绍一些在C中常用的加密与解密算法&#xff0c;这其中包括Xo…

「C++」入门

&#x1f387;个人主页&#xff1a;Ice_Sugar_7 &#x1f387;所属专栏&#xff1a;C启航 &#x1f387;欢迎点赞收藏加关注哦&#xff01; 文章目录 &#x1f349;前言&#x1f349;命名空间&#x1f34c;访问命名空间中的元素&#x1f34c;同名命名空间&#x1f34c;展开&…

企业编码生成程序Python毕业设计

&#xff08;1&#xff09;生成6位数字防伪编码。当用户在主程序界面中输入数字“1”菜单项时&#xff0c;将进入“生成6位数字防伪编码 &#xff08;213563型&#xff09;”的功能执行任务。此时要求输入生成防伪码的数量&#xff0c;可以根据需要输入生成防伪码的数量。按下&…

京东数据采集(京东数据运营):怎样快速获取京东市场大数据?

相信京东平台的很多品牌方们都有做数据分析的需求&#xff0c;但面对多而杂的市场数据&#xff0c;很多运营者都没有思路。单依靠肉眼来看&#xff0c;很多商品的类目、销售成绩、价格分布等运营者也未必清楚。 其实对于京东平台上市场数据的获取&#xff0c;品牌可以直接借助一…

使用VC++设计程序:实现常见的三种图像插值算法:最近邻插值,双线性插值,立方卷积插值

图像放大的三种插值算法 获取源工程可访问gitee可在此工程的基础上进行学习。 该工程的其他文章&#xff1a; 01- 一元熵值、二维熵值 02- 图像平移变换&#xff0c;图像缩放、图像裁剪、图像对角线镜像以及图像的旋转 03-邻域平均平滑算法、中值滤波算法、K近邻均值滤波器 04-…

C语言从入门到精通之【表达式和语句】

1 表达式 表达式由运算符和运算对象组成&#xff0c;最简单的表达式一个单独的运算对象。每个表达式都有一个值&#xff0c;并且是根据运算符优先级规定的顺序来执行&#xff0c;以下是一些表达式&#xff1a; 4 -6 421 a*(b c/d)/20 q 5*2 x q % 3 #q > 3 2 语句 语句…

[带余除法寻找公共节点]二叉树

二叉树 题目描述 如上图所示&#xff0c;由正整数1, 2, 3, ...组成了一棵无限大的二叉树。从某一个结点到根结点&#xff08;编号是1的结点&#xff09;都有一条唯一的路径&#xff0c;比如从10到根结点的路径是(10, 5, 2, 1)&#xff0c;从4到根结点的路径是(4, 2, 1)&#x…

cjson库打包数据实现方法

使用 cJson 库&#xff0c;在C语言环境下&#xff0c;打包一个cJson字符串&#xff1a; int CreateArryJsonString(void) {cJSON *cJsonArr cJSON_CreateArray();cJSON *sJsonObj1 cJSON_CreateObject();cJSON_AddStringToObject(sJsonObj1, "test1", "test1…

机器学习【03】在本地浏览器使用远程服务器的Jupyter Notebook【conda环境】

1.激活虚拟环境 conda activate 虚拟环境名字2.虚拟环境下安装jupyter notebook pip install jupyter3.配置 jupyter 文件 在 Jupyter Notebook 的配置目录中生成一个配置文件 jupyter_notebook_config.py jupyter notebook --generate-config3.设置密码 jupyter notebook …

信息素养大赛知识点

基础理论准备 开放存储期刊 开放存取期刊是一种免费的网络期刊&#xff0c;旨在使所有用户都可以通过因特网无限制地访问期刊论文全文。此种期刊一般采用作者付费出版、读者免费获得、无限制使用的运作模式&#xff0c;论文版权由作者保留。在论文质量控制方面&#xff0c;oa…

设备树是什么?

设备树&#xff1a; 设备树DTS(Device Tree Source) 描述设备信息的独立的文件。 为什么要引入设备树&#xff1f; 随着芯片的发展&#xff0c;Linux内核中就包含着越来越多这些描述设备的代码&#xff0c;导致Linux内核代码会很臃肿。因此引入了设备树文件&#xff0c;从…

论文阅读:“Appearance Capture and Modeling of Human Teeth”

文章目录 AbstractIntroductionMethod OverviewTeeth Appearance ModelEnamelDentinGingiva and oral cavity Data AcquisitionImage captureGeometry capture ResultsReferences Abstract 如果要为电影&#xff0c;游戏或其他类型的项目创建在虚拟环境中显示的人类角色&#…

什么是零拷贝 、零拷贝优化方案 - 真正的零拷贝,哪些地方会用到零拷贝技术

文章目录 什么是零拷贝3、零拷贝优化方案 - 真正的零拷贝哪些地方会用到零拷贝技术 现在来谈谈零拷贝&#xff0c;以及在开发中哪些地方使用到零拷贝。 开干… 什么是零拷贝 零拷贝指的是&#xff0c;从一个存储区域到另一个存储区域的copy任务无需CPU参与就可完成。零拷贝的底…

lv11 嵌入式开发 C工程与寄存器封装 10

目录 1 C语言工程介绍 1.1 工程模板介绍 1.2 启动代码分析 2 C语言实现LED实验 2.1 C语言如何实现寄存器读写 2.2 实现LED实验 2.3 练习 1 C语言工程介绍 1.1 工程模板介绍 工程目录&#xff0c;后续代码都会利用到这个目录 interface.c 写了一个main函数的框架 int …

基于springboot实现学生成绩管理系统项目【项目源码+论文说明】计算机毕业设计

基于springboot实现学生成绩管理系统演示 摘要 随着信息技术和网络技术的飞速发展&#xff0c;人类已进入全新信息化时代&#xff0c;传统管理技术已无法高效&#xff0c;便捷地管理信息。为了迎合时代需求&#xff0c;优化管理效率&#xff0c;各种各样的管理系统应运而生&am…

***Linux常用命令及解释

1、查看Linux的版本信息 1.1、uname -a 1.2、cat /etc/issue 1.3、cat /proc/version 1.4、hostnamectl 通过使用hostnamectl命令&#xff0c;可以查询和更改系统主机名&#xff0c;并且还可以查看Linux的发行版和内核版本。 2、删除文件 3、修改目录权限 4、解压文件 5、…

5 个适用于 Windows 的顶级免费数据恢复软件

对于计算机来说&#xff0c;最重要的是用户数据。除了您的数据之外&#xff0c;有关计算机的其他所有内容都是可替换的。这三个是数据丢失的最常见原因&#xff1a; 文件/文件夹删除丢失分区分区损坏 文件/文件夹删除 文件/文件夹删除是最常见的数据丢失类型。大多数时候&am…

基于springboot实现农机电招平台系统项目【项目源码+论文说明】计算机毕业设计

基于springboot实现农机电招平台系统演示 摘要 随着农机电招行业的不断发展&#xff0c;农机电招在现实生活中的使用和普及&#xff0c;农机电招行业成为近年内出现的一个新行业&#xff0c;并且能够成为大群众广为认可和接受的行为和选择。设计农机电招平台的目的就是借助计算…

visual Studio MFC 绘制单一颜色三角形、渐变颜色边框三角形、渐变填充三角形、边框渐变的正方形与填充渐变的正方形实例

MFC 绘制三角形 本文使用visual Studio MFC 平台实现绘制单一颜色三角形、渐变颜色边框三角形、渐变填充三角形、边框渐变的正方形与填充渐变的正方形. 关于基础工程的创建请参考Visual Studio 使用MFC 单文档工程绘制单一颜色直线和绘制渐变颜色的直线 文章目录 MFC 绘制三角形…