抽象类和接口(全)

news2025/6/13 23:31:44

一、抽象类

1.概念:如果⼀个类中没有包含⾜够的信息来描绘⼀个具体的对象,这样的类就是抽象类。

                像是没有实际⼯作的⽅法,我们可以把它设计成⼀个抽象⽅法,包含抽象⽅法的类我们称为抽象类。

2.语法

在Java中,⼀个类如果被 abstract 修饰称为抽象类,抽象类中被abstract 修饰的⽅法称为抽象⽅法,抽象⽅法不⽤给出具体的实现体。

public abstract class Shape {
    //抽象方法:被abstract修饰的方法,没有方法体
    abstract public void draw();
    abstract void calcArea();

    //抽象类也是类,也可以增加普通方法和属性
    public double getArea(){
        return area;
    }

    protected double area;//面积
}

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

3.抽象类的特性

(1)抽象类不能直接实例化对象

Shape sahpe = new Shape();

//编译错误
Error:(30, 23) java: Shape是抽象的; ⽆法实例化

(2)抽象方法不能是private的,也不能被final和static修饰(抽象类注定要被继承,内部的抽象方法要被重写)

(3)抽象类必须被继承,并且继承后子类要重写父类中的抽象方法,否则子类也是抽象类,必须要使用abstract修饰(如果子类也是抽象类,那么它的子类要重写其父类和父类的父类的抽象方法)

//抽象类:被abstract修饰的类
public abstract class Shape {
    //抽象方法:被abstract修饰的方法,没有方法体
    abstract public void draw();
    abstract void calcArea();
    //抽象类也是类,也可以增加普通方法和属性
    public double getArea(){
        return area;
    }

    protected double area;//面积
}


public class Rect extends Shape{
    private double length;
    private double width;
    public Rect(double length, double width) {
        this.length = length;
        this.width = width;
    }
    public void draw(){
        System.out.println("矩形:length="+length+"width="+width);
    }

    public void calcArea(){
        area = length*width;
    }

}


public class Circle extends Shape{
    private double r;
    final private static double PI = 3.14;
    public Circle(double r){
        this.r = r;
    }

    public void draw(){
        System.out.println("圆:r = "+r);
    }

    public void calcArea(){
        area = PI*r*r;
    }
}


public class Triangle extends Shape{
    private double a;
    private double b;
    private double c;
    @Override
    public void draw() {
        System.out.println("三⻆形: a = "+a + " b = "+b+" c = "+c);
    }

    @Override
    void calcArea() {

    }
}

(4).抽象类中不一定包含抽象方法,但是有抽象方法的类一定是抽象类

(5).抽象方法中可以有构造方法,供子类创建对象时初始化父类的成员变量

4.抽象类的作用

抽象类的使用相当于是多了一重编译器的校验。

在上述代码中,实际工作是由子类完成的,那么如果误用成了父类,普通的类编译器不会报错,但是父类是抽象类就会在实例化的时候提示错误,尽早发现问题。

二、接口

1.概念

在Java中,接口可以看成是多个类的公共规范,是一种引用数据类型

2.语法

public interface 接口名称{
    //抽象方法
    public abstract void method1();// public abstract是固定搭配,可以不写
    public void method2();
    abstract void method3();
    void method4();

    //注意:在接口中上述写法都是抽象方法,但是更推荐方式4,代码更加简洁
 }

#注:

(1)创建接口时,接口的命名一般是以大写的字母I开头

(2)接口的命名一般使用形容词性的单词(后面+able)

(3)阿里编码规范中约定,接口中的方法和属性不要加任何修饰符号,保持代码的简洁性。

3.接口的使用

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

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

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

//鼠标类,实现USB接口
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("鼠标点击");
    }
}


//键盘类,实现USB接口
public class KeyBoard implements USB {
    @Override
    public void openDevice() {
        System.out.println("打开键盘");
    }

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

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


//笔记本类:使用USB设备
public class Computer {
    public void powerOn(){
        System.out.println("打开笔记本电脑");
    }

    public void powerOff(){
        System.out.println("关闭笔记本电脑");
    }

    public void useDevice(USB usb){
        usb.openDevice();
        if(usb instanceof Mouse){
            Mouse mouse = (Mouse)usb;
            mouse.click();
        } else if (usb instanceof KeyBoard) {
            KeyBoard keyBoard = (KeyBoard) usb;
            keyBoard.inPut();
        }
        usb.closeDevice();
    }
}


//测试类
public class TestUSB {
    public static void main(String[] args) {
        Computer computer = new Computer();
        computer.powerOn();

        //使用鼠标设备
        computer.useDevice(new Mouse());

        //使用键盘设备
        computer.useDevice(new KeyBoard());

        computer.powerOff();
    }
}

instanceof是用于检查比较的,避免出现ClassCastException异常

4.特性

(1)接口是一种引用类型,但是不能直接new接口的对象

(2)即接⼝中的⽅法会被隐式的指定为public  abstract

(3)接口中的方法不能在接口中实现,只能由实现接口的类来实现

(4)重写接口中的方法时,不能使用默认的访问权限

(5)接口中可以含有变量,但是接口中的变量会被隐式的指定为public static final变量

(6)接口中不能有静态代码块和构造方法

(7)接口虽然不是类,但是接口编译完成后字节码文件的后缀格式也是.class

(8)如果类没有实现接口中的所有抽象方法,则类必须设置为抽象类

5.实现多个接口

Java中不⽀持多继承,但是⼀个类可以实现多个接⼝。

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

}

public interface IFlying {
    void fly();
}

public interface IRunning {
    void run();
}

public interface ISwimming {
    void swim();
}

public class Duck extends Animal implements IRunning,ISwimming,IFlying{
    public Duck(String name) {
        super(name);
    }

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

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

    @Override
    public void swim() {
        System.out.println(this.name+"正在漂在水上");
    }

}

这样设计可以让程序员不必关注具体类型,而是只关注某个类是否具备某种能力

6.接口之间的继承

在Java中,类和类之间是单继承的,⼀个类可以实现多个接⼝,接⼝与接⼝之间可以多继承。即:⽤ 接⼝可以达到多继承的⽬的。

接⼝可以继承⼀个接⼝,达到复⽤的效果. 使⽤extends关键字.

7.接⼝使⽤实例

例:对象之间进⾏⼤⼩关系⽐较

(1)使⽤Comparable接⼝

public class Student implements Comparable<Student>{
    private String name;
    private int score;

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

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



    @Override
    public int compareTo(Student o) {
//        Student s = (Student) o;
//        if(this.score > s.score){
//            return -1;
//        } else if (this.score > s.score) {
//            return 1;
//        }else {
//            return 0;
//        }
        return this.score-o.score;
        //return this.name.compareTo(o.name);
    }
}


public class Test {
    public static void main(String[] args) {
        Student s1 = new Student("zhangsan",10);
        Student s2 = new Student("lisi",20);
        System.out.println(s1.compareTo(s2));
    }
}

(2)使⽤Comparator接⼝

public class ScoreComparator implements Comparator<Student> {

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

public class NameComparator implements Comparator<Student> {


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

public class Test {
    public static void main(String[] args) {
        Student s1 = new Student("zhangsan",10);
        Student s2 = new Student("lisi",20);
        //根据分数进行比较
        ScoreComparator scoreComparator = new ScoreComparator();
        System.out.println(scoreComparator.compare(s1,s2));

        //根据姓名比较
        NameComparator nameComparator = new NameComparator();
        System.out.println(nameComparator.compare(s1,s2));
    }
}

8.Clonable 接⼝和深拷⻉

Java 中内置了⼀些很有⽤的接⼝,Clonable就是其中之⼀.

Object 类中存在⼀个clone⽅法,调⽤这个⽅法可以创建⼀个对象的"拷⻉".但是要想合法调⽤clone ⽅法,必须要先实现Clonable接⼝,否则就会抛出CloneNotSupportedException异常.

public class Animal implements Cloneable{
    private String name;
    public Animal clone(){
        Animal o = null;
        try{
            o = (Animal) super.clone();
        }catch(CloneNotSupportedException e){
            e.printStackTrace();
        }
        return o;
    }
}

public class Test {
    public static void main(String[] args) {
        Animal animal = new Animal();
        Animal animal2 = animal.clone();
        System.out.println(animal == animal2);
    }
}

#注:try-catch用来处理克隆过程中可能出现的异常的(try尝试调用并执行父类Object的clone方法,catch则是捕获异常,是一种校验)

(1)浅拷贝

public class Person implements Cloneable{
    public Money money = new Money();
    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }

}


public class Money {
    public double m = 99.99;
}


public class TestDemo3 {
    public static void main(String[] args) throws
            CloneNotSupportedException {
        Person person1 = new Person();
        Person person2 = (Person) person1.clone();
        System.out.println(" 通过 person2 修改前的结果 ");
        System.out.println(person1.money.m);
        System.out.println(person2.money.m);
        person2.money.m = 13.6;

        System.out.println("通过person2 修改后的结果 ");
        System.out.println(person1.money.m);
        System.out.println(person2.money.m);
    }
}

就像是上面的代码,只是拷贝了Person,它的Money没有被拷贝,这就叫做浅拷贝

(2)深拷贝(在浅拷贝的基础上连同Money一起拷贝)

protected Object clone()
            throws CloneNotSupportedException {
        //return super.clone();
        Person tmp = (Person)super.clone();
        tmp.m = (Money) this.m.clone();
        return tmp;
    }
}

9.抽象类和接口的区别

核⼼区别:抽象类中可以包含普通⽅法和普通字段,这样的普通⽅法和字段可以被⼦类直接使⽤(不必重写), ⽽接⼝中不能包含普通⽅法,⼦类必须重写所有的抽象⽅法.

三、Object类

Object是Java默认提供的⼀个类。Java⾥⾯除了Object类,所有的类都是存在继承关系的。默认会继 承Object⽗类。即所有类的对象都可以使⽤Object的引⽤进⾏接收

Object类也存在有定义好的⼀些⽅法,我们主要来熟悉这⼏个⽅法:equals()⽅法,hashcode()⽅法。

1.equals⽅法

equals⽅法默认是按照地址⽐较,如果要⽐较对象中内容,必须重写Object中的equals⽅法

class Person{
     ...
     @Override
     public boolean equals(Object obj) {
         if (obj == null) {
             return false ; 
         }
         if(this == obj) {
             return true ; 
         }
         // 不是Person类对象 
         if (!(obj instanceof Person)) {
             return false ; 
         }
         Person person = (Person) obj ; // 向下转型,⽐较属性值 
         return this.name.equals(person.name) && this.age==person.age ; 
    }
}

2.hashcode⽅法

了hashCode()这个⽅法,他帮我算了⼀个具体的对象位置,这⾥⾯涉及数据结构,但是还没学数据结构,没法讲述,所以只能说它是个内存地址。然后调⽤Integer.toHexString()⽅法, 将这个地址以16进制输出。

像重写equals⽅法⼀样,我们也可以重写hashcode()⽅法。

 class Person {
     public String name;
     public int age;
     public Person(String name, int age) {
         this.name = name;
         this.age = age;
     }
     @Override
     public int hashCode() {
         return Objects.hash(name, age);
     }
 }
 public class TestDemo4 {
     public static void main(String[] args) {
         Person per1 = new Person("gaobo", 20) ;
         Person per2 = new Person("gaobo", 20) ;
         System.out.println(per1.hashCode());
         System.out.println(per2.hashCode());
     }
 }
 //执⾏结果
 
 460141958
 460141958

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

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

相关文章

实战三:开发网页端界面完成黑白视频转为彩色视频

​一、需求描述 设计一个简单的视频上色应用&#xff0c;用户可以通过网页界面上传黑白视频&#xff0c;系统会自动将其转换为彩色视频。整个过程对用户来说非常简单直观&#xff0c;不需要了解技术细节。 效果图 ​二、实现思路 总体思路&#xff1a; 用户通过Gradio界面上…

系统掌握PyTorch:图解张量、Autograd、DataLoader、nn.Module与实战模型

本文较长&#xff0c;建议点赞收藏&#xff0c;以免遗失。更多AI大模型应用开发学习视频及资料&#xff0c;尽在聚客AI学院。 本文通过代码驱动的方式&#xff0c;系统讲解PyTorch核心概念和实战技巧&#xff0c;涵盖张量操作、自动微分、数据加载、模型构建和训练全流程&#…

nnUNet V2修改网络——暴力替换网络为UNet++

更换前,要用nnUNet V2跑通所用数据集,证明nnUNet V2、数据集、运行环境等没有问题 阅读nnU-Net V2 的 U-Net结构,初步了解要修改的网络,知己知彼,修改起来才能游刃有余。 U-Net存在两个局限,一是网络的最佳深度因应用场景而异,这取决于任务的难度和可用于训练的标注数…

论文阅读:LLM4Drive: A Survey of Large Language Models for Autonomous Driving

地址&#xff1a;LLM4Drive: A Survey of Large Language Models for Autonomous Driving 摘要翻译 自动驾驶技术作为推动交通和城市出行变革的催化剂&#xff0c;正从基于规则的系统向数据驱动策略转变。传统的模块化系统受限于级联模块间的累积误差和缺乏灵活性的预设规则。…

Cilium动手实验室: 精通之旅---13.Cilium LoadBalancer IPAM and L2 Service Announcement

Cilium动手实验室: 精通之旅---13.Cilium LoadBalancer IPAM and L2 Service Announcement 1. LAB环境2. L2公告策略2.1 部署Death Star2.2 访问服务2.3 部署L2公告策略2.4 服务宣告 3. 可视化 ARP 流量3.1 部署新服务3.2 准备可视化3.3 再次请求 4. 自动IPAM4.1 IPAM Pool4.2 …

数学建模-滑翔伞伞翼面积的设计,运动状态计算和优化 !

我们考虑滑翔伞的伞翼面积设计问题以及运动状态描述。滑翔伞的性能主要取决于伞翼面积、气动特性以及飞行员的重量。我们的目标是建立数学模型来描述滑翔伞的运动状态,并优化伞翼面积的设计。 一、问题分析 滑翔伞在飞行过程中受到重力、升力和阻力的作用。升力和阻力与伞翼面…

tauri项目,如何在rust端读取电脑环境变量

如果想在前端通过调用来获取环境变量的值&#xff0c;可以通过标准的依赖&#xff1a; std::env::var(name).ok() 想在前端通过调用来获取&#xff0c;可以写一个command函数&#xff1a; #[tauri::command] pub fn get_env_var(name: String) -> Result<String, Stri…

MyBatis中关于缓存的理解

MyBatis缓存 MyBatis系统当中默认定义两级缓存&#xff1a;一级缓存、二级缓存 默认情况下&#xff0c;只有一级缓存开启&#xff08;sqlSession级别的缓存&#xff09;二级缓存需要手动开启配置&#xff0c;需要局域namespace级别的缓存 一级缓存&#xff08;本地缓存&#…

【Linux手册】探秘系统世界:从用户交互到硬件底层的全链路工作之旅

目录 前言 操作系统与驱动程序 是什么&#xff0c;为什么 怎么做 system call 用户操作接口 总结 前言 日常生活中&#xff0c;我们在使用电子设备时&#xff0c;我们所输入执行的每一条指令最终大多都会作用到硬件上&#xff0c;比如下载一款软件最终会下载到硬盘上&am…

通过MicroSip配置自己的freeswitch服务器进行调试记录

之前用docker安装的freeswitch的&#xff0c;启动是正常的&#xff0c; 但用下面的Microsip连接不上 主要原因有可能一下几个 1、通过下面命令可以看 [rootlocalhost default]# docker exec -it freeswitch fs_cli -x "sofia status profile internal"Name …

【C++】纯虚函数类外可以写实现吗?

1. 答案 先说答案&#xff0c;可以。 2.代码测试 .h头文件 #include <iostream> #include <string>// 抽象基类 class AbstractBase { public:AbstractBase() default;virtual ~AbstractBase() default; // 默认析构函数public:virtual int PureVirtualFunct…

springboot 日志类切面,接口成功记录日志,失败不记录

springboot 日志类切面&#xff0c;接口成功记录日志&#xff0c;失败不记录 自定义一个注解方法 import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target;/***…

Linux部署私有文件管理系统MinIO

最近需要用到一个文件管理服务&#xff0c;但是又不想花钱&#xff0c;所以就想着自己搭建一个&#xff0c;刚好我们用的一个开源框架已经集成了MinIO&#xff0c;所以就选了这个 我这边对文件服务性能要求不是太高&#xff0c;单机版就可以 安装非常简单&#xff0c;几个命令就…

Ubuntu系统复制(U盘-电脑硬盘)

所需环境 电脑自带硬盘&#xff1a;1块 (1T) U盘1&#xff1a;Ubuntu系统引导盘&#xff08;用于“U盘2”复制到“电脑自带硬盘”&#xff09; U盘2&#xff1a;Ubuntu系统盘&#xff08;1T&#xff0c;用于被复制&#xff09; &#xff01;&#xff01;&#xff01;建议“电脑…

认识CMake并使用CMake构建自己的第一个项目

1.CMake的作用和优势 跨平台支持&#xff1a;CMake支持多种操作系统和编译器&#xff0c;使用同一份构建配置可以在不同的环境中使用 简化配置&#xff1a;通过CMakeLists.txt文件&#xff0c;用户可以定义项目结构、依赖项、编译选项等&#xff0c;无需手动编写复杂的构建脚本…

HybridVLA——让单一LLM同时具备扩散和自回归动作预测能力:训练时既扩散也回归,但推理时则扩散

前言 如上一篇文章《dexcap升级版之DexWild》中的前言部分所说&#xff0c;在叠衣服的过程中&#xff0c;我会带着团队对比各种模型、方法、策略&#xff0c;毕竟针对各个场景始终寻找更优的解决方案&#xff0c;是我个人和我司「七月在线」的职责之一 且个人认为&#xff0c…

协议转换利器,profinet转ethercat网关的两大派系,各有千秋

随着工业以太网的发展&#xff0c;其高效、便捷、协议开放、易于冗余等诸多优点&#xff0c;被越来越多的工业现场所采用。西门子SIMATIC S7-1200/1500系列PLC集成有Profinet接口&#xff0c;具有实时性、开放性&#xff0c;使用TCP/IP和IT标准&#xff0c;符合基于工业以太网的…

9-Oracle 23 ai Vector Search 特性 知识准备

很多小伙伴是不是参加了 免费认证课程&#xff08;限时至2025/5/15&#xff09; Oracle AI Vector Search 1Z0-184-25考试&#xff0c;都顺利拿到certified了没。 各行各业的AI 大模型的到来&#xff0c;传统的数据库中的SQL还能不能打&#xff0c;结构化和非结构的话数据如何和…

mac:大模型系列测试

0 MAC 前几天经过学生优惠以及国补17K入手了mac studio,然后这两天亲自测试其模型行运用能力如何&#xff0c;是否支持微调、推理速度等能力。下面进入正文。 1 mac 与 unsloth 按照下面的进行安装以及测试&#xff0c;是可以跑通文章里面的代码。训练速度也是很快的。 注意…

DBLP数据库是什么?

DBLP&#xff08;Digital Bibliography & Library Project&#xff09;Computer Science Bibliography是全球著名的计算机科学出版物的开放书目数据库。DBLP所收录的期刊和会议论文质量较高&#xff0c;数据库文献更新速度很快&#xff0c;很好地反映了国际计算机科学学术研…