当前位置: 首页 > news >正文

【JavaSE笔记】抽象类与接口

一、抽象类

1、概念

在面向对象的概念中,所有的对象都是通过类来描绘的,但是反过来,并不是所有的类都是用来描绘对象的,如果一个类中没有包含足够的信息来描绘一个具体的对象,这样的类就是抽象类
image-20230706105753546
image-20230706105829968

package demo2;
class Shape{public void draw(){System.out.println("画图形!");}
}
class Cycle extends Shape{@Overridepublic void draw() {System.out.println("⭕");}
}
class Rect extends Shape{@Overridepublic void draw() {System.out.println("矩形");}
}
public class Test {public static void drawMap(Shape shape){shape.draw();}public static void main(String[] args) {drawMap(new Rect());drawMap(new Cycle());}
}

在打印图形例子中, 我们发现, 父类 Shape 中的 draw 方法好像并没有什么实际工作,。即使父类的draw方法里面不写任何内容,也不影响程序的正常进行。主要的绘制图形都是由 Shape的各种子类的 draw 方法来完成的。像这种没有实际工作的方法, 我们可以把它设计成一个抽象方法(abstract method), 包含抽象方法的类我们称为 抽象类(abstract class)

抽象方法:这个方法没有具体的实现,使用关键字abstract进行修饰。

抽象类:不能完全代表一个具体的对象,此时使用abstract来修饰这个类。

2、语法

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

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

比如,将上面的Shape类改为抽象类。

//Shape 是一个抽象类,它包含普通方法、属性和构造方法。
abstract class Shape {// 普通属性:表示形状的颜色private String color;// 抽象方法:子类必须覆盖此方法以提供具体的实现public abstract void draw();// 构造方法:为抽象类 Shape 初始化颜色属性public Shape(String color) {this.color = color;}// 普通方法:打印形状的颜色public void printColor() {System.out.println("Shape color: " + color);}
}class Cycle extends Shape {// 覆盖抽象方法 draw()@Overridepublic void draw() {System.out.println("⭕");}// 子类构造方法调用父类构造方法,初始化颜色属性public Cycle(String color) {super(color);}
}class Rect extends Shape {// 覆盖抽象方法 draw()@Overridepublic void draw() {System.out.println("矩形");}// 子类构造方法调用父类构造方法,初始化颜色属性public Rect(String color) {super(color);}
}

3、注意

抽象类需要注意的地方:

  • 抽象类和抽象方法都是使用abstract进行修饰的
  • 抽象类不能进行实例化,但是普通类可以
  • 抽象类中不一定包含抽象方法,但是包含抽象方法的类一定是抽象类
  • 抽象类中可以定义普通的成员变量和成员方法
  • 当普通类继承抽象类,此时在普通类中,一定要重写抽象类中的抽象方法
  • 抽象类存在的最大意义,就是为了被继承
  • 当一个抽象类继承一个抽象类,此时不需要重写。当一个普通类继承了抽象类,那么所有没有重写的抽象方法都要进行重写
  • 抽象方法不能被finalstatic修饰,因为抽象方法要被子类重写
  • final关键字不可能同时作用在一个方法或者类上
  • 抽象类中可以有构造方法,供子类创建对象时,初始化父类的成员变量

4、作用

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

【问题】普通的类也可以被继承呀, 普通的方法也可以被重写呀, 为啥非得用抽象类和抽象方法呢?

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

很多语法存在的意义都是为了 “预防出错”, 例如 final 也是类似. 创建的变量用户不去修改, 不就相当于常量嘛? 但是加上final 能够在不小心误修改的时候, 让编译器及时提醒我们。

二、接口

1、概念

在现实生活中,接口的例子比比皆是,比如:笔记本上的USB口,电源插座等。
以电脑的USB口为例:可以插U盘、鼠标、键盘…所有符合USB协议的设备

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

2、语法

接口的定义格式与定义类的格式基本相同,将class关键字换成 interface 关键字,就定义了一个接口。

public interface 接口名称{
// 抽象方法public abstract void method1(); // public abstract 是固定搭配,可以不写public void method2();abstract void method3();void method4();
// 注意:在接口中上述写法都是抽象方法,跟推荐方式4,代码更简洁
}

提示:

  • 创建接口时, 接口的命名一般以大写字母 I 开头

  • 接口的命名一般使用 “形容词” 词性的单词

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

接口中,不能有实现的方法,但是有2种类型的方法需要注意:

1、静态方法可以有具体的实现

2、这个方法被default关键字修饰,也是可以的。

接口需要注意的地方:

  • 接口是使用interface来定义的
  • 接口当中的方法默认是public abstract修饰的
  • 接口中的成员变量默认是public static final修饰的
  • 接口也不能通过关键字new来进行实例化
  • 类和接口之间,我们使用关键字implements来进行关联
  • 当一个类实现一个接口后,这个类必须重写这个接口种的抽象方法
  • 当接口当中存在default方法,可以选择重写,也可以选择不重写

3、实现多个接口

在Java中,类和类之间是单继承的,一个类只能有一个父类,即Java中不支持多继承,但是一个类可以实现多个接口。下面通过类来表示一组动物。

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

另外我们再提供一组接口, 分别表示 “会飞的”, “会跑的”, “会游泳的”

interface IFlying {void fly();
}
interface IRunning {void run();
}
interface ISwimming {void swim();
}

接下来我们创建几个具体的动物

猫,是会跑的

class Cat extends Animal implements IRunning {public Cat(String name) {super(name);
}@Overridepublic void run() {System.out.println(this.name + "正在用四条腿跑");}
}

鱼,是会游泳的

class Fish extends Animal implements ISwimming {public Fish(String name) {super(name);
}@Overridepublic void swim() {System.out.println(this.name + "正在用尾巴游泳");}
}

青蛙, 是既能跑, 又能游的

class Frog extends Animal implements IRunning, ISwimming {public Frog(String name) {super(name);
}@Overridepublic void run() {System.out.println(this.name + "正在往前跳");}@Overridepublic void swim() {System.out.println(this.name + "正在蹬腿游泳");}
}

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

上面的代码展示了 Java 面向对象编程中最常见的用法: 一个类继承一个父类, 同时实现多种接口

继承表达的含义是 is - a 语义, 而接口表达的含义是 具有 xxx 特性

猫是一种动物, 具有会跑的特性.

青蛙也是一种动物, 既能跑, 也能游泳

鸭子也是一种动物, 既能跑, 也能游, 还能飞

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

例如, 现在实现一个方法, 叫 “散步”

public static void walk(IRunning running) {System.out.println("我带着伙伴去散步");running.run();
}

在这个 walk 方法内部, 我们并不关注到底是哪种动物, 只要参数是会跑的, 就行

Cat cat = new Cat("小猫");
walk(cat);
Frog frog = new Frog("小青蛙");
walk(frog);
// 执行结果
我带着伙伴去散步
小猫正在用四条腿跑
我带着伙伴去散步
小青蛙正在往前跳

4、接口间的继承

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

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

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

通过接口继承创建一个新的接口 IAmphibious 表示 “两栖的”。此时实现接口创建的 Frog 类, 就继续要实现 run 方法, 也需要实现 swim 方法。

接口间的继承相当于把多个接口合并在一起

5、抽象类和接口的区别

核心区别: 抽象类中可以包含普通方法和普通字段, 这样的普通方法和字段可以被子类直接使用(不必重写), 而接口中不能包含普通方法, 子类必须重写所有的抽象方法。如之前写的 Animal 例子. 此处的 Animal 中包含一个 name 这样的属性, 这个属性在任何子类中都是存在的。因此此处的 Animal 只能作为一个抽象类, 而不应该成为一个接口。

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

举个例子:假设我们正在为一个动物园编写一个程序。动物园的动物有一些共同的特征,如年龄、体重等,但它们的行为各不相同,例如叫声和移动方式。为了表示这些共同特征和行为,我们可以使用抽象类和接口。

抽象类:首先,我们可以创建一个名为Animal的抽象类。这个抽象类可以包含共同的属性(如年龄和体重)和一些抽象方法(如makeSoundmove)。在这个例子中,Animal抽象类的代码可能如下所示:

public abstract class Animal {protected int age;protected double weight;public Animal(int age, double weight) {this.age = age;this.weight = weight;}public abstract void makeSound();public abstract void move();
}

接口:同时,我们可以创建一个名为Swimmable的接口,表示动物园中能够游泳的动物。这个接口可以包含一个swim方法。Swimmable接口的代码可能如下所示:

public interface Swimmable {void swim();
}

现在,我们可以创建具体的动物类,如TigerDolphinTiger类可以继承Animal抽象类,并实现makeSoundmove方法。而Dolphin类既可以继承Animal抽象类,也可以实现Swimmable接口,表示它还具有游泳的能力。

image-20230710152012420

三、Object类

Object类是Java所有类的始祖,在Java中的每一个类都是由它拓展而来的。

Java里面除了Object类,所有的类都是存在继承关系的。默认会继承Object父类。即所有类的对象都可以使用Object的引用进行接收。

在Java中,只有基本类型不是对象,所有的数组类型,不管是对象数组还是基本类型的数组,都拓展了Object类。

class Person {}
class Student {}public class Test {public static void main(String[] args) {function(new Person());function(new Student());}public static void function(Object obj) {System.out.println(obj);}
}
// 执行结果:
// Person@1b6d3586
// Student@4554617c

在开发之中,Object类是参数的最高统一类型。但是Object类也存在有定义好的一些方法。

image-20230710174209365

1、获取对象的信息

// Object类中的toString()方法实现:
public String toString() {return getClass().getName() + "@" + Integer.toHexString(hashCode());
}

2、对象比较equals方法

在Java中,== 进行比较时:

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

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

如果要比较对象中内容,必须重写Object中的equals方法,因为equals方法默认也是按照地址比较的(判断是否具有相同的引用)

// Object类中的equals方法
public boolean equals(Object obj) {return (this == obj); // 使用引用中的地址直接来进行比较
}
class Person {private String name;private int age;public Person(String name, int age) {this.age = age;this.name = name;}
}public class Test {public static void main(String[] args) {Person p1 = new Person("张三", 20);Person p2 = new Person("张三", 20);int a = 10;int b = 10;System.out.println(a == b); // 输出trueSystem.out.println(p1 == p2); // 输出falseSystem.out.println(p1.equals(p2)); // 输出false}
}

Person类重写equals方法后,然后比较:

class Person {private String name;private int age;public Person(String name, int age) {this.age = age;this.name = name;}@Overridepublic boolean equals(Object obj) {if (obj == null) {return false;}if (this == obj) {return true;}if (!(obj instanceof Person)) {return false;}Person person = (Person) obj;return this.name.equals(person.name) && this.age == person.age;}
}public class Test {public static void main(String[] args) {Person p1 = new Person("张三", 20);Person p2 = new Person("张三", 20);int a = 10;int b = 10;System.out.println(a == b); // 输出trueSystem.out.println(p1 == p2); // 输出falseSystem.out.println(p1.equals(p2)); // 输出true}
}

结论:比较对象中内容是否相同的时候,一定要重写equals方法。

3、 hashcode方法

public native int hashCode();

该方法是一个native方法,底层是由C/C++代码写的。

我们认为两个名字相同,年龄相同的对象,将存储在同一个位置,如果不重写hashcode()方法,我们可以来看示例:

class Person {public String name;public int age;public Person(String name, int age) {this.name = name;this.age = age;}
}public class TestDemo4 {public static void main(String[] args) {Person per1 = new Person("张三", 20);Person per2 = new Person("张三", 20);System.out.println(per1.hashCode());System.out.println(per2.hashCode());}
}
//执行结果
460141958
1163157884

注意事项:两个对象的hash值不一样

像重写equals方法一样,我们也可以重写hashcode()方法。此时我们再来看看。

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

注意事项:哈希值一样

结论:

1、hashcode方法用来确定对象在内存中存储的位置是否相同

2、事实上hashCode()在散列表中才有用,在其它情况下没用。

3、在散列表中hashCode() 的作用是获取对象的散列码,进而确定该对象在散列表中的位置。

4、toString方法

在Java中,toString()方法是Object类的一个成员方法,而所有的类都继承自Object类。因此,任何Java对象都有toString()方法。

该方法的主要目的是返回对象的字符串表示形式。

toString()的默认实现是返回对象的类名,后面接上"@",然后跟上对象的哈希码的无符号十六进制表示。

Person person = new Person();
System.out.println(person.toString()); 
// 默认可能会输出类似“Person@4a574795”

为了提供对象的更有意义的字符串表示,通常我们会在类中重写toString()方法。

public class Person {private String name;private int age;public Person(String name, int age) {this.name = name;this.age = age;}@Overridepublic String toString() {return "Person{name='" + name + "', age=" + age + "}";}
}

现在,当我们打印一个Person对象时:

Person person = new Person("Alice", 25);
System.out.println(person); // 输出:Person{name='Alice', age=25}

注意,当你打印一个对象(例如:System.out.println(person);)Java实际上是隐式调用这个对象的toString()方法。

相关文章:

【JavaSE笔记】抽象类与接口

一、抽象类 1、概念 在面向对象的概念中,所有的对象都是通过类来描绘的,但是反过来,并不是所有的类都是用来描绘对象的,如果一个类中没有包含足够的信息来描绘一个具体的对象,这样的类就是抽象类。 package demo2…...

详谈操作系统中的内核态和用户态

不知道大家有没有思考过这样一个问题:什么是处理器(CPU)的状态?🤔 其实CPU和人一样,没有执行程序的时候,是没有什么状态的,当它执行的程序是用户程序的时候就叫用户态,当执行的程序是操作系统的代码时就叫系统态或者内…...

OpenWrt KernelPackage分析

一. 前言 KernelPackage是OpenWrt用来编译内核模块的函数,其实KernelPackage后面会调用BuildPackage,这里会一块将BuildPackage也顺便分析,本文以gpio-button-hotplug驱动模块为例,讲解整个编译过程。 gpio-button-hotplug驱动编译…...

第 363 场 LeetCode 周赛题解

A 计算 K 置位下标对应元素的和 模拟 class Solution { public:int pop_cnt(int x) {//求x的二进制表示中的1的位数int res 0;for (; x; x >> 1)if (x & 1)res;return res;}int sumIndicesWithKSetBits(vector<int> &nums, int k) {int res 0;for (int i…...

ffplay源码解析-main入口函数

main入口函数 初始化 变量、缓存区、SDL窗口初始化等 int main(int argc, char **argv) {int flags;VideoState *is; // av_log_set_level(AV_LOG_TRACE);init_dynload();av_log_set_flags(AV_LOG_SKIP_REPEATED);parse_loglevel(argc, argv, options);/// av_log_set_le…...

这些Coding套路你不会还不知道吧?

对于一名程序员来说&#xff0c;编码进阶是成为优秀工程师非常重要的一步&#xff0c;它可以让我们更加熟练地掌握编程&#xff0c;深入理解数据结构和算法&#xff0c;从而更好地完成复杂的任务&#xff0c;提高工作效率。而我认为熟练使用设计模式就是编码进阶的最好方式之一…...

Spring Boot深度解析:快速开发的秘密

&#x1f337;&#x1f341; 博主猫头虎&#xff08;&#x1f405;&#x1f43e;&#xff09;带您 Go to New World✨&#x1f341; &#x1f984; 博客首页——&#x1f405;&#x1f43e;猫头虎的博客&#x1f390; &#x1f433; 《面试题大全专栏》 &#x1f995; 文章图文…...

mysql数据库备份(mysqldump)

mysqldump命令备份数据 mysqldump -u root -p --databases 数据库1 数据库2 > xxx.sqlmysqldump常用操作示例 1. 备份全部数据库的数据和结构 mysqldump -uroot -p123456 -A > /data/mysqlbackup/mydb.sql2. 备份全部数据库的结构&#xff08;加 -d 参数&#xff09; …...

linux Nginx+Tomcat负载均衡、动静分离

linux NginxTomcat负载均衡、动静分离 1、Tomcat的基本介绍1.1Tomcat是什么&#xff1f;1.2Tomcat的构成组件1.3Tomcat的核心功能1.4Tomcat请求过程 2、Tomcat部署2.1安装tomcat2.2优化tomcat启动速度2.4主要目录说明 3、Tomcat 虚拟主机配置3.1创建fsj和mws项目目录和文件3.2修…...

ts 枚举类型原理及其应用详解

ts 枚举类型介绍 TypeScript的枚举类型是一种特殊的数据类型&#xff0c;它允许开发者为一组相关值定义一个共同的名称&#xff0c;使我们可以更清晰、更一致地使用这些值。 枚举类型在TypeScript中用enum关键字定义&#xff0c;每个枚举值默认都是数字类型&#xff0c;从0开…...

腾讯mini项目-【指标监控服务重构】2023-08-23

今日已办 进度和问题汇总 请求合并 feature/venus tracefeature/venus metricfeature/profile-otel-baserunner-stylebugfix/profile-logger-Syncfeature/profile_otelclient_enable_config 完成otel 开关 trace-采样metrice-reader 已经都在各自服务器运行&#xff0c;并接入…...

C- ssize_t size_t

size_t 和 ssize_t 都是在 C 和 C 的标准库中定义的数据类型&#xff0c;它们通常用于表示大小和长度。然而&#xff0c;它们有关键的区别。 size_t: 定义&#xff1a;size_t 是一个无符号整数类型&#xff0c;它是适合表示对象的大小的类型。在 POSIX 中&#xff0c;它也用于…...

ubuntu20.04 Supervisor 开机自启动脚本一文配置

前言: 最近发现一种非常好的开机启动服务方式,不光可以开机自启动,而且还可以进行开机节点的进程守护,这样大大确保了线程的稳定情况,这种服务甚至可以守护开机的进程,所以比之前设置 rc.local 开机自启动脚本一文配置节点好出很多,它甚至可以使用网页登录监管我开机自启…...

【面试刷题】——函数指针和指针函数

“函数指针”&#xff08;function pointer&#xff09;和 “指针函数”&#xff08;pointer to function&#xff09;是两个不同的概念&#xff0c;它们涉及到指针和函数的结合使用。 函数指针&#xff08;Function Pointer&#xff09;&#xff1a; 函数指针是指向函数的指…...

目标分类笔记(一): 利用包含多个网络多种训练策略的框架来完成多目标分类任务(从数据准备到训练测试部署的完整流程)

目标分类 一、目标分类介绍1.1 二分类和多分类的区别1.2 单标签和多标签输出的区别 二、代码获取三、数据集准备四、环境搭建4.1 环境测试 五、模型训练六、模型测试6.1 多标签训练-单标签输出结果6.2 多标签训练-多标签输出结果 一、目标分类介绍 目标分类是一种监督学习任务…...

【100天精通Python】Day61:Python 数据分析_Pandas可视化功能:绘制饼图,箱线图,散点图,散点图矩阵,热力图,面积图等(示例+代码)

目录 1 Pandas 可视化功能 2 Pandas绘图实例 2.1 绘制线图 2.2 绘制柱状图 2.3 绘制随机散点图 2.4 绘制饼图 2.5 绘制箱线图A 2.6 绘制箱线图B 2.7 绘制散点图矩阵 2.8 绘制面积图 2.9 绘制热力图 2.10 绘制核密度估计图 1 Pandas 可视化功能 pandas是一个强大的数…...

2023华为产品测评官-开发者之声 | 华为云CodeArts征文活动,多重好礼邀您发声!

"2023华为产品测评官&#xff0d;开发者之声"活动激发了众多开发者和技术爱好者的热情&#xff0c;他们纷纷递交了精心编写的产品测评报告。活动社群充满活力&#xff0c;参与者们热衷于交流讨论&#xff0c;互相帮助解决问题&#xff0c;一起探索云技术的无限可能。…...

Python 图形化界面基础篇:获取文本框中的用户输入

Python 图形化界面基础篇&#xff1a;获取文本框中的用户输入 引言 Tkinter 库简介步骤1&#xff1a;导入 Tkinter 模块步骤2&#xff1a;创建 Tkinter 窗口步骤3&#xff1a;创建文本框步骤4&#xff1a;获取文本框中的用户输入步骤5&#xff1a;启动 Tkinter 主事件循环 完整…...

【驱动开发】实现三盏灯的控制,编写应用程序测试

head.h #ifndef __HEAD_H__ #define __HEAD_H__//LED1:PE10 //LED2:PF10 //LED3:PE8#define LED_RCC 0X50000A28 //使能GPIO#define LED_MODER 0X50006000 //设置输出模式 #define LED_ODR 0X50006014 //设置输出高低电平#define LED2_MODER 0X50007000 …...

Vue3+ElementUI使用

<!DOCTYPE html> <html> <head><meta charset"UTF-8"><meta name"viewport" content"initial-scale1.0,maximum-scale1.0,minimum-scale1.0,user-scalable0, widthdevice-width"/><!-- 引入样式 --><lin…...

2.Vue编写一个app

1.src中重要的组成 1.1main.ts // 引入createApp用于创建应用 import { createApp } from "vue"; // 引用App根组件 import App from ./App.vue;createApp(App).mount(#app)1.2 App.vue 其中要写三种标签 <template> <!--html--> </template>…...

高等数学(下)题型笔记(八)空间解析几何与向量代数

目录 0 前言 1 向量的点乘 1.1 基本公式 1.2 例题 2 向量的叉乘 2.1 基础知识 2.2 例题 3 空间平面方程 3.1 基础知识 3.2 例题 4 空间直线方程 4.1 基础知识 4.2 例题 5 旋转曲面及其方程 5.1 基础知识 5.2 例题 6 空间曲面的法线与切平面 6.1 基础知识 6.2…...

Cloudflare 从 Nginx 到 Pingora:性能、效率与安全的全面升级

在互联网的快速发展中&#xff0c;高性能、高效率和高安全性的网络服务成为了各大互联网基础设施提供商的核心追求。Cloudflare 作为全球领先的互联网安全和基础设施公司&#xff0c;近期做出了一个重大技术决策&#xff1a;弃用长期使用的 Nginx&#xff0c;转而采用其内部开发…...

MySQL 8.0 OCP 英文题库解析(十三)

Oracle 为庆祝 MySQL 30 周年&#xff0c;截止到 2025.07.31 之前。所有人均可以免费考取原价245美元的MySQL OCP 认证。 从今天开始&#xff0c;将英文题库免费公布出来&#xff0c;并进行解析&#xff0c;帮助大家在一个月之内轻松通过OCP认证。 本期公布试题111~120 试题1…...

AI编程--插件对比分析:CodeRider、GitHub Copilot及其他

AI编程插件对比分析&#xff1a;CodeRider、GitHub Copilot及其他 随着人工智能技术的快速发展&#xff0c;AI编程插件已成为提升开发者生产力的重要工具。CodeRider和GitHub Copilot作为市场上的领先者&#xff0c;分别以其独特的特性和生态系统吸引了大量开发者。本文将从功…...

用docker来安装部署freeswitch记录

今天刚才测试一个callcenter的项目&#xff0c;所以尝试安装freeswitch 1、使用轩辕镜像 - 中国开发者首选的专业 Docker 镜像加速服务平台 编辑下面/etc/docker/daemon.json文件为 {"registry-mirrors": ["https://docker.xuanyuan.me"] }同时可以进入轩…...

Maven 概述、安装、配置、仓库、私服详解

目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...

USB Over IP专用硬件的5个特点

USB over IP技术通过将USB协议数据封装在标准TCP/IP网络数据包中&#xff0c;从根本上改变了USB连接。这允许客户端通过局域网或广域网远程访问和控制物理连接到服务器的USB设备&#xff08;如专用硬件设备&#xff09;&#xff0c;从而消除了直接物理连接的需要。USB over IP的…...

以光量子为例,详解量子获取方式

光量子技术获取量子比特可在室温下进行。该方式有望通过与名为硅光子学&#xff08;silicon photonics&#xff09;的光波导&#xff08;optical waveguide&#xff09;芯片制造技术和光纤等光通信技术相结合来实现量子计算机。量子力学中&#xff0c;光既是波又是粒子。光子本…...

毫米波雷达基础理论(3D+4D)

3D、4D毫米波雷达基础知识及厂商选型 PreView : https://mp.weixin.qq.com/s/bQkju4r6med7I3TBGJI_bQ 1. FMCW毫米波雷达基础知识 主要参考博文&#xff1a; 一文入门汽车毫米波雷达基本原理 &#xff1a;https://mp.weixin.qq.com/s/_EN7A5lKcz2Eh8dLnjE19w 毫米波雷达基础…...