【抽象类和接口】

news2024/11/17 0:05:46

目录

  • 1.抽象类
    • 1.1什么是抽象类
    • 1.2抽象类语法
    • 1.3抽象类与普通类的区别
  • 2.抽象类的特性
    • 2.1 特性
    • 2.2抽象类的作用
  • 3.接口
    • 3.1什么是接口
    • 3.2语法规范
    • 3.3接口的使用
    • 3.4接口的特性
    • 3.5 实现多个接口
    • 3.6 接口的继承
  • 4.接口的实例
  • 5.Clonable 接口和深拷贝
    • 5.1 浅拷贝
    • 5.2深拷贝
  • 6. 抽象类和接口的区别

1.抽象类

1.1什么是抽象类

在我们Java面对对象的概念中,所有的对象都是通过类来描述的,但是有一些对象不能通过类来描述。
如果一个类中没有足够的系信息去描绘一个具体的对象,这个类就是抽象类。
在这里插入图片描述

说明:
1.Animal是动物类,每个动物都有叫的方法,但由于Animal不是一个具体的动物,因此其内部eat()方法无法具体实现
2.Dog是狗类,首先狗是动物,因此与Animal是继承关系,其次狗是一种具体的动物,狗叫:汪汪汪,其eat()可以实现
3.Cat是猫类,首先猫是动物,因此与Animal是继承关系,其次猫是一种具体的动物,猫叫:崛瞄瞄,其eat()可以实现
4.因此:Animal可以设计为“抽象类"

我们可以看出来,父类的eat()方法,并不是一个实际的工作,主要的各种子类的eat()方法来实现的,像这种没有实际工作的方法,我们一般可以设为一个抽象方法。包含抽象方法的类称为抽象类。

1.2抽象类语法

如果一个类,被abstract修饰,那么这个类就是一个抽象类,这个类中,被abstract修饰的方法,称为抽象方法。

注意:抽象类也是类,内部可以包含普通方法和属性,甚至构造方法

abstract class A
{
    abstract public void func();
    
}
class B extends A
{
    @Override
    public void func() {
        System.out.println("B的方法");
    }
}
public class Test {
    public static void main(String[] args) {
        A a=new B();
        a.func();
    }
}

1.3抽象类与普通类的区别

1.抽象类不能实例化,普通类可以实例化
在这里插入图片描述
2.抽象类中,可以包含抽象方法和普通方法,但是普通类只能包含非抽象方法。
在这里插入图片描述

2.抽象类的特性

2.1 特性

1.抽象类使用abstract修饰类
2.抽象类不能被实例化。
3.此时在抽象类当中,可以有抽象方法,或者非抽象方法!
4.什么是抽象方法,一个方法被abstract修饰,没有具体的实现。只要包含抽象方法,这个类必须是抽象类!
5.当一个普通类继承了这个抽象类,必须重写抽象类当中的抽象方法!
6.抽象类存在的最大的意义,就是为了被继承!
7.抽象方法不能被private , final , static修饰。所以一定要满足方法重写的规则!!
8.当一个子类没有重写抽象的父类的方法,可以把当前子类变为abstract修饰。
9.抽象类中,不一定包含抽象方法

2.2抽象类的作用

抽象类本身不能被实例化, 要想使用, 只能创建该抽象类的子类. 然后让子类重写抽象类中的抽象方法.

确实如此. 但是使用抽象类相当于多了一重编译器的校验.
使用抽象类的场景就如上面的代码, 实际工作不应该由父类完成, 而应由子类完成. 那么此时如果不小心误用成父类了, 使用普通类编译器是不会报错的. 但是父类是抽象类就会在实例化的时候提示错误, 让我们尽早发现问题.

3.接口

3.1什么是接口

接口就是公共的行为规范标准,大家在实现时,只要符合规范标准,就可以通用。
在Java中,接口可以看成是:多个类的公共规范,是一种引用数据类型

3.2语法规范

我们接口的定义跟类差不多,就是把class换位interface关键字,就可以定义了一个接口。

interface IShape{
    public int age=2;
    public String name="1";
    //默认是这个
    public static final String sex="1";

    //方法默认这个
    public abstract void draw();

    //也可以
    default public  void func()
    {
        System.out.println("66666666");
    }

    public static void staticfunc()
    {
        System.out.println("staticfunc");
    }
}

注意:

  1. 创建接口时, 接口的命名一般以大写字母 I 开头.
  2. 接口的命名一般使用 “形容词” 词性的单词.
  3. 阿里编码规范中约定, 接口中的方法和属性不要加任何修饰符号, 保持代码的简洁性.

3.3接口的使用

接口不能直接的使用,必须要有一个类来实现这个接口,实现接口中的抽象方法

子类和父类之间是extends 继承关系,类与接口之间是 implements 实现关系。

public class 类名称 implements 接口名称{
// ...
}
public class Mouse implements USB{

    @Override
    public void openDevice() {
        System.out.println("打开鼠标");
    }

    @Override
    public void closeDevice() {

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

3.4接口的特性

大家如果想用这个东西你必须实现一下我的规范。
1.使用关键字interface来定义接口
2.接口不能被实例化
3.接口当中的成员默认是public static final
4.接口当中的方法不写也是默认为public abstract的
5.接口当中的方法不能有具体的实现,但是从JDK8开始可以写一个default修饰的方法
6.接口当中不能有构造方法
7.接口需要被类实现,使用关键字implements
8.接口当中可以有static修饰的方法!
9. 重写接口中方法时,不能使用默认的访问权限
10.接口中不能有静态代码块和构造方法

3.5 实现多个接口

在Java中,类和类之间是单继承的,一个类只能有一个父类,即Java中不支持多继承,但是一个类可以实现多个接口。

下面通过类来表示一组动物.。
并且在定义几个接口表示跑,游泳,飞等等。
接下来我们创建几个具体的动物,具体实现这几个接口

注意:一个类实现多个接口时,每个接口中的抽象方法都要实现,否则类必须设置为抽象类。

abstract class Animal {
    public String name;

    public Animal(String name) {
        this.name = name;
    }
}
interface IRunning {
    void run();
}
interface ISwimming {
    void swim();
}

interface IFly {
    void fly();
}

class Dog extends Animal implements IRunning {

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

    @Override
    public void run() {
        System.out.println(name +" 正在用四条狗腿跑!");
    }
}

class Fish extends Animal implements ISwimming{

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

    @Override
    public void swim() {
        System.out.println(name + "正在游泳!");
    }
}
class Bird extends Animal implements IFly {

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

    @Override
    public void fly() {
        System.out.println(name + "正在飞!");
    }
}
class Duck extends Animal implements IRunning,IFly,ISwimming {

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

    @Override
    public void run() {
        System.out.println(name + "正在用两条腿跑!");
    }

    @Override
    public void swim() {
        System.out.println(name + "正在用两条腿在游泳!");
    }

    @Override
    public void fly() {
        System.out.println(name + "正在用翅膀飞!");
    }
}

class Robot implements IRunning{

    @Override
    public void run() {
        System.out.println("机器人在用机器腿跑步!");
    }
}

public class Test4 {

    /**
     * 只要实现了 IRunning 接口的 都可以接收
     * @param iRunning
     */
    public static void walk(IRunning iRunning) {
        iRunning.run();
    }

    public static void swim(ISwimming iSwimming) {
        iSwimming.swim();
    }

    /**
     * 一定是一个动物
     * @param animal
     */
    public static void func(Animal animal) {

    }

    public static void main(String[] args) {
        walk(new Dog("旺财"));
        walk(new Duck("唐老鸭"));
        walk(new Robot());

        System.out.println("======");
        swim(new Fish("七秒"));
        swim(new Duck("唐老鸭2号"));
    }
}

这样设计有什么好处呢? 时刻牢记多态的好处, 让程序猿忘记类型. 有了接口之后, 类的使用者就不必关注具体类型,而只关注某个类是否具备某种能力.

3.6 接口的继承

在Java中,类和类之间是单继承的,一个类可以实现多个接口,接口与接口之间可以多继承。即:用接口可以达到多继承的目的。

接口可以继承一个接口, 达到复用的效果. 使用 extends 关键字.

interface IRunning {
void run();
}
interface ISwimming {
void swim();
}
// 两栖的动物, 既能跑, 也能游
interface IAmphibious extends IRunning, ISwimming {
}
class Frog implements IAmphibious {
...
}

4.接口的实例

当我们定义了一个Stydent类,里面定义了两个属性,一个姓名,一个年纪。
当我们 new 了三个对象的时候,我们想给他排序,这应该怎么办?当我们只用原本的sort()方法会发现报错。

Exception in thread "main" java.lang.ClassCastException: Student cannot be cast to java.lang.Comparable

那么我们应该怎么办?当我们的对象里面有两个属性,这个时候我们不会知道按照那个属性去排序,就会出现错误。
所以我们就要重写方法,让这个方法按照我们想排序的属性去进行比较。

package demo3;


import java.util.Arrays;
import java.util.Comparator;

class Student
{
    public String name;
    public int age;
    public int score;

    public Student(String name, int age, int score) {
        this.name = name;
        this.age = age;
        this.score = score;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", score=" + score +
                '}';
    }
}

class Agecomparator implements Comparator<Student>
{

    @Override
    public int compare(Student o1, Student o2) {
        return o1.age-o2.age;
    }
}

class Scorecomparator implements Comparator<Student>
{

    @Override
    public int compare(Student o1, Student o2) {
        return o1.score-o2.score;
    }
}

class Namecomparator implements Comparator<Student>
{

    @Override
    public int compare(Student o1, Student o2) {
        return o1.name.compareTo(o2.name);
    }
}
public class test {
    public static void main(String[] args) {
        Student[] students=new Student[3];
        students[0]=new Student("zhangsan",10,10);
        students[1]=new Student("lisi",20,20);
        students[2]=new Student("wangwu",30,30);


        Agecomparator getcomparator=new Agecomparator();
        Arrays.sort(students,getcomparator);
        System.out.println(Arrays.toString(students));
        System.out.println("===========");
       Scorecomparator scorecomparator=new Scorecomparator();
        Arrays.sort(students,scorecomparator);
        System.out.println(Arrays.toString(students));
        System.out.println("===============");
        Namecomparator namecomparator=new Namecomparator();
        Arrays.sort(students,namecomparator);
        System.out.println(Arrays.toString(students));
    }
}

0

5.Clonable 接口和深拷贝

Java 中内置了一些很有用的接口, Clonable 就是其中之一.

Object 类中存在一个 clone 方法, 调用这个方法可以创建一个对象的 “拷贝”. 但是要想合法调用 clone 方法, 必须要先实现 Clonable 接口, 否则就会抛出 CloneNotSupportedException 异常

5.1 浅拷贝

class Money
{
    public double money=12.25;

}
class Student implements Cloneable
{
    public String name;
    public Money m=new Money();

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                '}';
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}
public class test {
    public static void main(String[] args) throws CloneNotSupportedException {
        Student student=new Student();
        student.name="123";
        Student student1=(Student) student.clone();
        System.out.println(student);
        System.out.println(student1);
        System.out.println("==========");
        student1.m.money=99;
        System.out.println(student.m.money);
        System.out.println(student1.m.money);
    }
}

在这里插入图片描述
如上代码,我们可以看到,通过clone,我们只是拷贝了Student对象。但是Student对象中的Money对象,并
没有拷贝。通过Student1这个引用修改了m的值后,Student1这个引用访问m的时候,值也发生了改变。这里
就是发生了浅拷贝。
在这里插入图片描述

5.2深拷贝

package demo4;

class Money implements Cloneable
{
    public double money=12.25;

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}
class Student implements Cloneable
{
    public String name;
    public Money m=new Money();

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                '}';
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        Student student=(Student) super.clone();
        student.m=(Money)this.m.clone();
        return student;
        //return super.clone();
    }
}
public class test {
    public static void main(String[] args) throws CloneNotSupportedException{
        Student student=new Student();
        Student student1=(Student) student.clone();
        System.out.println(student.m.money);
        System.out.println(student1.m.money);
        System.out.println("=============");
        student1.m.money=99;
        System.out.println(student.m.money);
        System.out.println(student1.m.money);
    }
    public static void main1(String[] args) throws CloneNotSupportedException {
        Student student=new Student();
        student.name="123";
        Student student1=(Student) student.clone();
        System.out.println(student);
        System.out.println(student1);

    }
}

在这里插入图片描述
如上代码,我们可以看到,通过clone,我们只是拷贝了Student对象。并且Student对象中的Money对象也进行了拷贝。通过Student1这个引用修改了m的值后,Student个引用访问m的时候,值也发生了改变。这里
就是发生了深拷贝。
在这里插入图片描述

6. 抽象类和接口的区别

核心区别: 抽象类中可以包含普通方法和普通字段, 这样的普通方法和字段可以被子类直接使用(不必重写), 而接口中不能包含普通方法,子类必须重写所有的抽象方法.

如之前写的 Animal 例子. 此处的 Animal 中包含一个 name 这样的属性, 这个属性在任何子类中都是存在的. 因此此处的 Animal 只能作为一个抽象类, 而不应该成为一个接口。

在这里插入图片描述

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

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

相关文章

English Learning - L3 作业打卡 Lesson4 Day27 2023.5.31 周三

English Learning - L3 作业打卡 Lesson4 Day27 2023.5.31 周三 引言&#x1f349;句1: It is so crowded that we are packed like sardines – just like small fish in a can.成分划分弱读连读爆破语调 &#x1f349;句2: My supervisor at work is sometimes out to lunch.…

设计模式之database/sql 与Gorm设计原理

1.0 理解 database/sql 1.1 基本用法 - Quick Start 上面有几行错误 DSN相关知识&#xff1a; https://github.com/go-sql-driver/mysql#dsn-data-source-name https://en.wikipedia.org/wiki/Data_source_name 完整&#xff1a; 1.2 设计原理 极简接口设计原则&#xff1a; 对…

UNIX环境高级编程——高级I/O

14.1 引言 本章讨论高级I/O相关主题&#xff0c;包括&#xff1a; 非阻塞I/O&#xff1b;记录锁&#xff1b;I/O多路转接&#xff08;select、poll&#xff09;&#xff1b;异步I/O&#xff1b;readv和writev函数&#xff1b;存储映射I/O&#xff08;mmap&#xff09;。 14.…

Hesai激光雷达使用PTP时间同步

PTP是一个网络同步时钟的协议&#xff0c;全称是Precise Time Protocol&#xff0c;也称为IEEE 1588&#xff0c;其有IEEE1588v1和IEEE1588v2两个版本&#xff08;其中v1版本是为工业自动化测量和控制系统开发的&#xff0c;适用于工业局域网应用。v2版本是在v1版本的基础上&am…

Win11电脑突然没有声音了怎么办?

Win11电脑突然没有声音了怎么办&#xff1f;有用户电脑连接了音响之后&#xff0c;无论自己怎么调整都没有声音&#xff0c;那么遇到这个问题之后&#xff0c;要怎么去进行修复呢&#xff1f;如果你也遇到了没有电脑没有声音的情况&#xff0c;可以通过以下的方法来进行解决。 …

Vue (7)

文章目录 1. 单文件组件1.1 创建 .vue 文件1.2 vue 脚手架1.2.1 说明1.2.2 创建 vue 脚手架1.2.3 了解 vue_test 中的文件 1.2.4 render 函数 1.3 修改默认配置1.4 ref 属性1.5 props 配置项1.6 mixin 混入1.7 插件1.8 Scoped 样式 2. 组件化编码流程2.1 TodoList 案例总结 前言…

Pycharm设置Python每个文件开头自定义模板(带上声明字符编码、作者名、时间等)

Pycharm设置地址&#xff1a; 在File---settings---Editor---File and Code Templates---Python script 脚本里添加: 模板声明设置参考&#xff1a; # ---encoding:utf-8--- # Time : ${DATE} ${HOUR}:${MINUTE} # Author : 作者名 # Email &#xff1a;你的邮箱 # Sit…

Nginx启动,重启以及基本命令

1.启动nginx 进入nginx安装目录执行 ./sbin/nginx -c ./conf/nginx.conf 2.验证nginx配置文件是否正确 方法1. 进入nginx安装目录sbin下&#xff0c;输入命令 ./nginx -t 回显test is successful说明配置正确 方法2. 在启动nginx命令 -c 前加 -t ./sbin/nginx -t -c ./c…

一次诡异405 METHOD_NOT_ALLOWED “Request method ‘POST‘ not supported“问题排查记录

概述 任何稍微只要有一点经验的开发者都知道HTTP 405&#xff0c;表示方法不支持。如&#xff0c;本来是定义为POST接口&#xff0c;前端使用GET请求&#xff0c;就会报错。 但是我还真遇上一次405 METHOD_NOT_ALLOWED "Request method POST not supported"问题&am…

ReadDataByIdentifier(0x22)服务

ReadDataByIdentifier&#xff08;0x22&#xff09;服务 ReadDataByIdentifier服务允许客户端从一个或多个dataIdentifiers标识的服务器请求数据记录值。 客户端请求消息包含一个或多个两字节的dataIdentifier值&#xff0c;用于标识服务器维护的数据记录 允许的dataIdentifie…

【Azure】微软 Azure 基础解析(八)Azure 存储服务:探索Blob存储、队列存储、文件存储的特性与适用场景

本系列博文还在更新中&#xff0c;收录在专栏&#xff1a;「Azure探秘&#xff1a;构建云计算世界」 专栏中。 本系列文章列表如下&#xff1a; 【Azure】微软 Azure 基础解析&#xff08;三&#xff09;描述云计算运营中的 CapEx 与 OpEx&#xff0c;如何区分 CapEx 与 OpEx…

代码随想录第50天

1.买卖股票的最佳时机III&#xff1a; 动态规划五部曲详细分析一下&#xff1a; 确定dp数组以及下标的含义 一天一共就有五个状态&#xff0c; 没有操作 &#xff08;其实我们也可以不设置这个状态&#xff09;第一次持有股票第一次不持有股票第二次持有股票第二次不持有股…

2021年全国A级景区矢量分布数据(11969条)

一、景区定义 旅游景区是以旅游及其相关活动为主要功能或主要功能之一的空间或地域。本标准中旅游景区是指具有参观游览、休闲度假、康乐健身等功能&#xff0c;具备相应旅游服务设施并提供相应旅游服务的独立管理区。该管理区应有统一的经营管理机构和明确的地域范围。包括风景…

设计模式-中介者模式

中介者模式 问题背景中介者设计模式基本介绍原理 问题解决-代码示例注意事项和细节 问题背景 一提到中介&#xff0c;我们首先就能想到租房中介&#xff0c;有租房中介在我们需要租房子的时候可以给我们节省很大精力。 那没有中介我们要怎么租房呢&#xff1f; 我们可以想象一…

English Learning - L3 作业打卡 Lesson4 Day25 2023.5.29 周一

English Learning - L3 作业打卡 Lesson4 Day25 2023.5.29 周一 引言&#x1f349;句1: My husband has a good job.成分划分弱读连读爆破语调 &#x1f349;句2: He makes enough money to support our family.成分划分弱读连读语调 &#x1f349;句3: So we say he brings ho…

防火墙之部署服务器NAT

防火墙部署服务器NAT 原理概述&#xff1a; NAT&#xff08;Network Address Translation&#xff09;&#xff0c;是指网络地址转换&#xff0c;1994年提出的。 当在专用网内部的一些主机本来已经分配到了本地IP地址&#xff08;即仅在本专用网内使用的专用地址&#xff09;&a…

离散化以及树状数组

今天我们先来讲一讲什么叫做离散化&#xff08;简单的映射关系&#xff09; 一、离散化 一、概念&#xff1a;就是把一个无限的空间去映射到一个有限的空间中去&#xff08;通俗的可以理解成将数据相应的缩小&#xff09;为了更好的理解&#xff0c;请看下图&#xff1a; 已知…

90后测试员:“入职阿里,这一次,我决定不跳槽了...”

所谓“舒适”生活 记得上一份工作是去年听从了朋友的意见&#xff0c;“你一定要找一份舒适的工作&#xff0c;这样你一天就有好多时间玩&#xff0c;好多时间干自己想干的事情&#xff0c;摸鱼真香&#xff01;” 在这份“教导”下&#xff0c;开始了我的找工作之旅&#xf…

Day972.OAuth 2.0是要通过什么方式解决什么问题? -OAuth 2.0

OAuth 2.0是要通过什么方式&#xff1f;解决什么问题&#xff1f; 使用某个App 的时候&#xff0c;是直接使用了第三方帐号&#xff08;比如微信、微博&#xff09;登录&#xff0c;还是选择了重新注册新用户&#xff1f;如果选择了重新注册用户&#xff0c;那你还得上传头像、…