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

JavaSE【抽象类和接口】(抽象类、接口、实现多个接口、接口的继承)

一、抽象类

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

1.语法

// 抽象类:被 abstract 修饰的类
public abstract class Shape {
// 抽象方法:被 abstract 修饰的方法,没有方法体
        abstract public void draw ();
        abstract void calcArea ();
// 抽象类也是类,也可以增加普通方法和属性
        public double getArea (){
               return area ;
        }
        protected double area ; // 面积
}
写完之后,编译器可以看到抽象类 和 抽象方法 的图标

 

 

2.抽象类的特性 

1. 抽象类不能直接实例化自身对象,只能创建该抽象类的子类
2. 抽象方法不能是 private
3. 抽象方法不能被 fifinal static 修饰,因为抽象方法要被子类重写

4. 抽象类必须被继承,并且继承后子类要重写父类中的抽象方法,否则子类也是抽象类,必须要使用 abstract 修饰
5. 抽象类中不一定包含抽象方法,但是有抽象方法的类一定是抽象类
6. 抽象类中可以有构造方法,供子类创建对象时,初始化父类的成员变量
7.如果普通类A继承了抽象类,但不想重写该抽象类Shape的方法,这个普通类A前面就要用abstract修饰,但如果又有一个普通类B继承了这个A,那么B既要重写A的抽象方法,也要重写Shape的抽象方法

例子: 特性都在里面标注了


//抽象类,被abstract修饰的方法
abstract class Shape{//抽象类当中,可以和普通类一样,定义成员变量 和 成员方法//抽象类,被abstract修饰的方法public abstract void draw();//被final、private、static修饰的抽象方法是不可以的
}
//抽象类就是为了被继承
//当一个普通的类,继承了这个抽象类,那么需要重写这个抽象类中的所有抽象方法!!!
class Cycle extends Shape{@Overridepublic void draw() {System.out.println("圆形");}
}
class Rect extends Shape{@Overridepublic void draw() {System.out.println("矩形");}
}
//如果普通类A继承了抽象类,但不想重写该抽象类Shape的方法,这个普通类A前面就要用abstract修饰
//但如果又有一个普通类B继承了这个A,那么B既要重写A的抽象方法,也要重写Shape的抽象方法
abstract class A extends Shape{public abstract void test();
}
class B extends A{//重写Shape里的所有抽象方法@Overridepublic void draw() {}//重写A里的所有抽象方法@Overridepublic void test() {}
}
public class Test {public static void drawMap(Shape shape){shape.draw();}public static void main(String[] args) {//抽象类本身不能实例化对象//Shape shape = new Shape();//抽象类只能创建该抽象类的子类Shape shape = new Rect();Shape shape2 = new Cycle();drawMap(shape);drawMap(shape2);}
}

二、接口

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

1.语法

接口的定义格式与定义类的格式基本相同,将 class 关键字换成 interface 关键字,就定义了一个接口。
public interface 接口名称 {
// 抽象方法
        public abstract void method1 (); // public abstract 是固定搭配,可以不写
        public void method2 ();
        abstract void method3 ();
        void method4 ();
// 注意:在接口中上述写法都是抽象方法,跟推荐方式 4 ,代码更简洁
}

2.接口的使用

接口不能直接使用,必须要有一个 " 实现类 " " 实现 " 该接口,实现接口中的所有抽象方法。
public class 类名称 implements 接口名称 {
// ...
}
子类和父类之间是 extends 继承关系,类与接口之间是 implements 实现关系。

 4.接口特性

1. 接口类型是一种引用类型,但是不能直接 new 接口的对象
2. 接口里只能有抽象方法; dk8中:接口中还可以包含default、static方法。
3. 接口中的方法是不能在接口中实现的,只能由实现接口的类来实现,或者使用 static、default修饰的方法 (其中由接口实现的类,必须被重写,因为接口里的方法默认都是 public abstract 所修饰的!!!)(default修饰的可以重写也可以不重写)(static不能重写,可以直接通过类名调用)
4.  重写接口中方法时,不能使用默认的访问权限,只能是public
(因为子类的访问权限要大于父类)
5. 接口中可以含有变量,但是接口中的变量会被隐式的指定为 public static fifinal 变量
(相当于常量)
6.   接口中不能有代码块和构造方法
7. 接口虽然不是类,但是接口编译完成后字节码文件的后缀格式也是 .class
8. 如果类没有实现接口中的所有的抽象方法,则类必须设置为抽象类

//接口
interface IShape{//接口里的方法默认都是 public abstract 所修饰的!!!//全称 :public abstract void draw();void draw();//默认抽象方法//接口里只能有抽象方法,还有static、default修饰的方法(jdk8引入的)default public void test(){}static public void test2(){};//接口当中的成员变量 默认都是 public static final 修饰的!!!//实际上就是一个常量,常量一般大写字母表示int A = 1;public static int B = 2;public static final int C = 3;}
//类实现接口,使用implement
class Rect_i implements IShape{//需要重写接口的抽象方法@Overridepublic void draw() {System.out.println("矩形");}
}
class Flower_i implements IShape{@Overridepublic void draw() {System.out.println("花花");}
}
public class Test2 {public static void drawMap(IShape iShape){iShape.draw();}public static void main(String[] args) {//接口不能实例化自身//IShape iShape = new IShape();//接口只能创建该抽象类的子类IShape iShape1 = new Flower_i();IShape iShape2 = new Rect_i();drawMap(iShape1);drawMap(iShape2);System.out.println("================");IShape[] iShapes ={new Flower_i(),new Rect_i()};for (IShape x:iShapes) {drawMap(x);}}}

 

4.实现笔记本电脑使用USB鼠标、USB键盘的例子

1. USB 接口:包含打开设备、关闭设备功能
2. 笔记本类:包含开机功能、关机功能、使用 USB 设备功能
3. 鼠标类:实现 USB 接口,并具备点击功能
4. 键盘类:实现 USB 接口,并具备输入功能
package demo2;public interface USB {void openDevice();void closeDevice();
}
package demo2;public class Mouse implements USB{@Overridepublic void openDevice() {System.out.println("鼠标开始工作");}@Overridepublic void closeDevice() {System.out.println("鼠标结束工作");}public void click(){System.out.println("疯狂点击鼠标。。。。。。。。");}
}
package demo2;public class KeyBoard implements USB{@Overridepublic void openDevice() {System.out.println("键盘开始工作");}@Overridepublic void closeDevice() {System.out.println("键盘结束工作");}public void input(){System.out.println("疯狂敲打键盘。。。。。。。。。。。");}
}
package demo2;public class Computer {public void powerOn(){System.out.println("打开电脑!!");}public void powerOff(){System.out.println("关闭电脑!!");}public void useService(USB usb){usb.openDevice();//如果usb引用的对象是Mouse,强制类型转换到Mouse//如果usb引用的对象是KeyBoard,强制类型转换到KeyBoardif (usb instanceof Mouse){Mouse mouse = (Mouse) usb;mouse.click();} else if (usb instanceof KeyBoard) {KeyBoard keyBoard = (KeyBoard) usb;keyBoard.input();}usb.closeDevice();}
}
package demo2;public class Test {public static void main(String[] args) {Computer computer = new Computer();Mouse mouse = new Mouse();KeyBoard keyBoard = new KeyBoard();computer.powerOn();computer.useService(mouse);System.out.println("=================");computer.useService(keyBoard);computer.powerOff();}
}

 

5.实现多个接口 - 解决Java的多继承问题

Java 中,类和类之间是单继承的,一个类只能有一个父类,即 Java 中不支持多继承 ,但是 一个类可以实现多个接 。下面通过类来表示一组动物 .
狗是一种动物 , 具有会跑的特性 .
青蛙也是一种动物 , 既能跑 , 也能游泳
鸭子也是一种动物 , 既能跑 , 也能游 , 还能飞

 

 

package demo3;abstract class Animal{public String name;public int age;public Animal(String name, int age) {this.name = name;this.age = age;}public abstract void eat();}
interface IFly{void fly();
}
interface IRun{void run();
}
interface ISwim{void swim();
}
//狗是一个动物,具备跑这个功能
class Dog extends Animal implements IRun{public Dog(String name, int age) {super(name, age);}@Overridepublic void run() {System.out.println(this.name+"正在跑!!!");}@Overridepublic void eat() {System.out.println(this.name+"吃狗粮");}}
class Frog extends Animal implements IRun,ISwim{public Frog(String name,int age){super(name,age);}@Overridepublic void run() {System.out.println(this.name+"正在用4条腿跳着跑!!");}@Overridepublic void swim() {System.out.println(this.name+"正在蛙泳!!");}@Overridepublic void eat() {System.out.println(this.name+"吃蛙粮");}
}
class Duck extends Animal implements IRun,IFly,ISwim{public Duck(String name, int age) {super(name, age);}@Overridepublic void run() {System.out.println(this.name+"正在两只脚 跑!!!");}@Overridepublic void swim() {System.out.println(this.name+"正在 游泳!!!");}@Overridepublic void fly() {System.out.println(this.name+"正在用两只翅膀飞!!!");}@Overridepublic void eat() {System.out.println(this.name+"吃鸭粮");}
}
public class Test {public static void func1(Animal animal){animal.eat();}public static void run(IRun iRun){iRun.run();}public static void fly(IFly ifly){ifly.fly();}public static void swim(ISwim iSwim){iSwim.swim();}public static void main(String[] args) {run(new Duck("唐老鸭",1));swim(new Duck("唐老鸭",1));fly(new Duck("唐老鸭",1));System.out.println("========");run(new Dog("二狗子",2));System.out.println("========");run(new Frog("青蛙王子",3));swim(new Frog("青蛙王子",3));}public static void main1(String[] args) {
//        Animal animal = new Duck("唐老鸭",1);
//        Animal animal2 = new Dog("二狗子",2);
//        Animal animal3 = new Frog("青蛙王子",3);Animal[] animals = {new Duck("唐老鸭",1),new Dog("二狗子",2),new Frog("青蛙王子",3)};for (Animal x:animals) {func1(x);}}
}

 6.接口间的继承

package demo4extends;interface A{void testA();
}
interface B extends A{void testB();
}
class TestDemo1 implements B{@Overridepublic void testA() {}@Overridepublic void testB() {}
}
public class Test {
}

 7.接口的使用实例

1)给定一个学生对象数组, 对这个对象数组中的元素进行排序

 

 

 

 

方法1:类里重写comparaTo方法(方式固定)

package demo5;/*** 方法1:固定比较方式*/
class Student implements Comparable<Student>{public String name;public int age;public Student(String name, int age) {this.name = name;this.age = age;}@Overridepublic String toString() {return "Student{" +"name='" + name + '\'' +", age=" + age +'}';}@Overridepublic int compareTo(Student o) {if(this.age > o.age){return 1;} else if (this.age == o.age) {return 0;}else {return -1;}}
}
public class Test {public static void main(String[] args) {//两个引用类型比较大小Student student1 = new Student("zhangsan",10);Student student2 = new Student("lisi",20);//System.out.println(student1>student2);无法比较//因为,student是引用类型,里面存的是地址,无法直接通过大于小于符号比较大小//不知道拿什么作比较(是姓名还是年龄)//使用重写后的compareToSystem.out.println(student1.compareTo(student2));}public static void main1(String[] args) {//普通数值比较大小int a = 10;int b = 20;System.out.println(a > b);//false}
}

方法2:自定义一个类,写比较器(运用灵活)


import java.util.Comparator;/*** 方法2:可以根据需求,更改比较的对象* 比较器*/class Student {public String name;public int age;public Student(String name, int age) {this.name = name;this.age = age;}@Overridepublic String toString() {return "Student{" +"name='" + name + '\'' +", age=" + age +'}';}}
//根据年龄比较
class AgeComparator implements Comparator<Student>{@Overridepublic int compare(Student o1, Student o2) {return o1.age- o2.age;}
}
//根据姓名比较
class NameComparator implements Comparator<Student>{@Overridepublic int compare(Student o1, Student o2) {return o1.name.compareTo(o2.name);}
}
public class Test {public static void main(String[] args) {//两个引用类型比较大小Student student1 = new Student("zhangsan",10);Student student2 = new Student("lisi",20);AgeComparator ageComparator = new AgeComparator();System.out.println(ageComparator.compare(student1, student2));NameComparator nameComparator = new NameComparator();System.out.println(nameComparator.compare(student1, student2));}}

2)给students数组排序

package demo5;
import java.util.Arrays;
import java.util.Comparator;/*** 方法1:固定比较方式*/
//class Student implements Comparable<Student>{
//    public String name;
//    public int age;
//
//    public Student(String name, int age) {
//        this.name = name;
//        this.age = age;
//    }
//
//    @Override
//    public String toString() {
//        return "Student{" +
//                "name='" + name + '\'' +
//                ", age=" + age +
//                '}';
//    }
//
//    @Override
//    public int compareTo(Student o) {
//        if(this.age > o.age){
//            return 1;
//        } else if (this.age == o.age) {
//            return 0;
//        }else {
//            return -1;
//        }
//    }
//}
/*** 方法2:可以根据需求,更改比较的对象* 比较器*/class Student {public String name;public int age;public Student(String name, int age) {this.name = name;this.age = age;}@Overridepublic String toString() {return "Student{" +"name='" + name + '\'' +", age=" + age +'}';}}
//根据年龄比较
class AgeComparator implements Comparator<Student>{@Overridepublic int compare(Student o1, Student o2) {return o1.age- o2.age;}
}
//根据姓名比较
class NameComparator implements Comparator<Student>{@Overridepublic int compare(Student o1, Student o2) {return o1.name.compareTo(o2.name);}
}
public class Test {public static void main(String[] args) {
//        int[] array = {1,2,31,4};
//        Arrays.sort(array);
//        System.out.println(Arrays.toString(array));Student[] students = new Student[3];students[0] = new Student("zhangsan",10);students[1] = new Student("lisi",4);students[2] = new Student("abc",5);System.out.println("排序前:"+Arrays.toString(students));//方法1:可以用固定方法//Arrays.sort(students);//方法2:可以用自定义方法,比较器AgeComparator ageComparator = new AgeComparator();NameComparator nameComparator = new NameComparator();//Arrays.sort(students,ageComparator);Arrays.sort(students,nameComparator);System.out.println("排序后:"+Arrays.toString(students));}public static void main3(String[] args) {//两个引用类型比较大小Student student1 = new Student("zhangsan",10);Student student2 = new Student("lisi",20);//        AgeComparator ageComparator = new AgeComparator();
//        System.out.println(ageComparator.compare(student1, student2));
//
//        NameComparator nameComparator = new NameComparator();
//        System.out.println(nameComparator.compare(student1, student2));}public static void main2(String[] args) {//两个引用类型比较大小Student student1 = new Student("zhangsan",10);Student student2 = new Student("lisi",20);//System.out.println(student1>student2);无法比较//因为,student是引用类型,里面存的是地址,无法直接通过大于小于符号比较大小//不知道拿什么作比较(是姓名还是年龄)//使用重写后的compareTo//System.out.println(student1.compareTo(student2));}public static void main1(String[] args) {//普通数值比较大小int a = 10;int b = 20;System.out.println(a > b);//false}
}

方法1:固定方法

 

 

 

方法2:自定义方法,比较器

根据name排序 

 根据age排序

 

相关文章:

JavaSE【抽象类和接口】(抽象类、接口、实现多个接口、接口的继承)

一、抽象类 在 Java 中&#xff0c;一个类如果被 abstract 修饰称为抽象类&#xff0c;抽象类中被 abstract 修饰的方法称为抽象方法&#xff0c;抽象方法不用 给出具体的实现体。 1.语法 // 抽象类&#xff1a;被 abstract 修饰的类 public abstract class Shape { …...

微信小程序如何跳转H5页面

1、登录微信公众后台&#xff0c;进入【开发->开发管理->业务域名】&#xff0c;点击修改。 2、首先请下载校验文件&#xff0c;并将文件放置在域名根目录下。 我是把文件放在nginx主机的data目录下&#xff0c;然后通过增加nginx.config配置&#xff0c;重启nginx后可…...

C++(20):bit_cast

C++20之前如果想对不同的指针之间做类型转换需要通过reinterpret_cast,对于整数与指针之前的转换也需要通过reinterpret_cast: C++:reinterpret_cast_c++ reparant_cast_风静如云的博客-CSDN博客 但是reinterpret_cast的缺点是不同的编译环境下,无法包装转型的安全一致。 …...

STM32 低功耗-停止模式

STM32 停止模式 文章目录 STM32 停止模式第1章 低功耗模式简介第2章 停止模式简介2.1 进入停止模式2.1 退出停止模式 第3章 停止模式程序部分总结 第1章 低功耗模式简介 在 STM32 的正常工作中&#xff0c;具有四种工作模式&#xff1a;运行、睡眠、停止以及待机模式。 在系统…...

Hutool中 常用的工具类和方法

文章目录 日期时间工具类 DateUtil日期时间对象-DateTime类型转换工具类 Convert字符串工具类 StrUtil数字处理工具类 NumberUtilJavaBean的工具类 BeanUtil集合操作的工具类 CollUtilMap操作工具类 MapUtil数组工具-ArrayUtil唯一ID工具-IdUtilIO工具类-IoUtil加密解密工具类 …...

K8s(健康检查+滚动更新+优雅停机+弹性伸缩+Prometheus监控+配置分离)

前言 快速配置请直接跳转至汇总配置 K8s SpringBoot实现零宕机发布&#xff1a;健康检查滚动更新优雅停机弹性伸缩Prometheus监控配置分离&#xff08;镜像复用&#xff09; 配置 健康检查 健康检查类型&#xff1a;就绪探针&#xff08;readiness&#xff09; 存活探针&am…...

Django学习记录:使用ORM操作MySQL数据库并完成数据的增删改查

Django学习记录&#xff1a;使用ORM操作MySQL数据库并完成数据的增删改查 数据库操作 MySQL数据库pymysql Django开发操作数据库更简单&#xff0c;内部提供了ORM框架。 安装第三方模块 pip install mysqlclientORM可以做的事&#xff1a; 1、创建、修改、删除数据库中的…...

React Hooks 中的 useEffect(副作用)

useEffect 是什么&#xff1f; useEffect 是一个 React Hook&#xff0c;它允许你将组件与外部系统同步 当我们在 React 中使用 useEffect 这个 Hook 时&#xff0c;实际上是在告诉 React 在特定情况下执行我们定义的副作用函数。这种副作用函数可以处理一些与组件渲染结果无关…...

[CKA]考试之持久化存储卷PersistentVolume

由于最新的CKA考试改版&#xff0c;不允许存储书签&#xff0c;本博客致力怎么一步步从官网把答案找到&#xff0c;如何修改把题做对&#xff0c;下面开始我们的 CKA之旅 题目为&#xff1a; Task 创建一个pv&#xff0c;名字为app-config&#xff0c;大小为2Gi&#xff0c;…...

基于LLM的SQL应用程序开发实战(一)

基于LLM的SQL应用程序开发实战(一) 16.1 SQL on LLMs应用程序初始化 本节主要从案例代码的角度切入,探索ChatGPT以及大模型,尤其是从生产环境的视角,来思考具体的最佳实践。本节主要跟大家谈的是,在LangChain这样一个框架下,我们使用GPT-3.5或者GPT-4大模型,同时使用第…...

如何批量实现多行合并后居中

思路&#xff1a; 1.先填充数据 2.数据分类统计制作格式 3.格式刷刷制作出的格式 1.填充数据 思路&#xff1a;选中&#xff0c;F5定位空值&#xff0c;&#xff0c;⬆&#xff08;键盘上的上下左右哪里的上键&#xff09;&#xff0c;按住Ctrl然后按Enter。 2.数据分类统计…...

【深度学习_TensorFlow】手写数字识别

写在前面 到这里为止&#xff0c;我们已经学习完张量的常用操作方法&#xff0c;已具备实现大部分神经网络技术的基础储备了。这一章节我们将开启神经网络的学习&#xff0c;然而并不需要像学习前面那样了解大量的张量操作&#xff0c;而是将重点转向理解概念知识&#xff0c;…...

antv/l7地图,鼠标滚动,页面正常滑动-- 我们忽略的deltaY

背景 在官网项目中&#xff0c;需要使用一个地图&#xff0c;展示产品的分布区域及数量。希望的交互是&#xff0c;鼠标放上标点&#xff0c;tooltip展示地点和数量等信息。鼠标滚动&#xff0c;则页面随着滚动。但是鼠标事件是被地图代理了的&#xff0c;鼠标滚动意味着地图的…...

再续AM335x经典,米尔TI AM62x核心板上市,赋能新一代HMI

近十年来&#xff0c;AM335x芯片作为TI经典工业MPU产品&#xff0c;在工业处理器市场占据主流地位&#xff0c;其凭借GPMC高速并口、PRU协处理器等个性化硬件资源&#xff0c;在工业控制、能源电力、轨道交通、智慧医疗等领域广受用户欢迎。随着信息技术的快速发展&#xff0c;…...

springboot和Django哪一个做web服务器框架更好

目录 一、两者特点 二、各自优势 一、两者特点 编程语言&#xff1a; Spring Boot&#xff1a;使用 Java 编程语言。Django&#xff1a;使用 Python 编程语言。 生态系统和社区支持&#xff1a; Spring Boot&#xff1a;具有庞大的 Java 生态系统和强大的社区支持。适用于大型…...

C#核心知识回顾——21.归并排序

理解递归逻辑 一开始不会执行sort函数的 要先找到最小容量数组时 才会回头递归调用Sort进行排序 基本原理 归并 递归 合并 数组分左右 左右元素相比较 一侧用完放对面 不停放入新数组 递归不停分 分…...

基于netty的rpc远程调用

QPRC &#x1f680;&#x1f680;&#x1f680;这是一个手写RPC项目&#xff0c;用于实现远程过程调用&#xff08;RPC&#xff09;通信&#x1f680;&#x1f680;&#x1f680; 欢迎star串门&#xff1a;https://github.com/red-velet/ &#x1f680;Q-PRC 一、功能特性 …...

RabbitMQ输出日志配置

参考地址rabbitmq启用日志功能记录消息队列收发情况_rabbitmq开启日志_普通网友的博客-CSDN博客 启用日志插件命令 # 设置用户权限 rabbitmqctl set_user_tags mqtt-user administrator rabbitmqctl set_permissions -p / mqtt-user ".*" ".*" ".*&…...

解决一个Sqoop抽数慢的问题,yarn的ATSv2嵌入式HBASE崩溃引起

新搭建的一个Hadoop环境&#xff0c;用Sqoop批量抽数的时候发现特别慢&#xff0c;我们正常情况下是一个表一分钟左右&#xff0c;批量抽十几个表&#xff0c;也就是10分钟的样子&#xff0c;结果发现用了2个小时&#xff1a; 查看yarn日志 发现有如下情况&#xff1a; 主要有两…...

为Android构建现代应用——应用导航设计

在前一章节的实现中&#xff0c;Skeleton: Main structure&#xff0c;我们留下了几个 Jetpack 架构组件&#xff0c;这些组件将在本章中使用&#xff0c;例如 Composables、ViewModels、Navigation 和 Hilt。此外&#xff0c;我们还通过 Scaffold 集成了 TopAppBar 和 BottomA…...

Qt/C++开发监控GB28181系统/取流协议/同时支持udp/tcp被动/tcp主动

一、前言说明 在2011版本的gb28181协议中&#xff0c;拉取视频流只要求udp方式&#xff0c;从2016开始要求新增支持tcp被动和tcp主动两种方式&#xff0c;udp理论上会丢包的&#xff0c;所以实际使用过程可能会出现画面花屏的情况&#xff0c;而tcp肯定不丢包&#xff0c;起码…...

3.3.1_1 检错编码(奇偶校验码)

从这节课开始&#xff0c;我们会探讨数据链路层的差错控制功能&#xff0c;差错控制功能的主要目标是要发现并且解决一个帧内部的位错误&#xff0c;我们需要使用特殊的编码技术去发现帧内部的位错误&#xff0c;当我们发现位错误之后&#xff0c;通常来说有两种解决方案。第一…...

Debian系统简介

目录 Debian系统介绍 Debian版本介绍 Debian软件源介绍 软件包管理工具dpkg dpkg核心指令详解 安装软件包 卸载软件包 查询软件包状态 验证软件包完整性 手动处理依赖关系 dpkg vs apt Debian系统介绍 Debian 和 Ubuntu 都是基于 Debian内核 的 Linux 发行版&#xff…...

基于uniapp+WebSocket实现聊天对话、消息监听、消息推送、聊天室等功能,多端兼容

基于 ​UniApp + WebSocket​实现多端兼容的实时通讯系统,涵盖WebSocket连接建立、消息收发机制、多端兼容性配置、消息实时监听等功能,适配​微信小程序、H5、Android、iOS等终端 目录 技术选型分析WebSocket协议优势UniApp跨平台特性WebSocket 基础实现连接管理消息收发连接…...

CMake基础:构建流程详解

目录 1.CMake构建过程的基本流程 2.CMake构建的具体步骤 2.1.创建构建目录 2.2.使用 CMake 生成构建文件 2.3.编译和构建 2.4.清理构建文件 2.5.重新配置和构建 3.跨平台构建示例 4.工具链与交叉编译 5.CMake构建后的项目结构解析 5.1.CMake构建后的目录结构 5.2.构…...

Qwen3-Embedding-0.6B深度解析:多语言语义检索的轻量级利器

第一章 引言&#xff1a;语义表示的新时代挑战与Qwen3的破局之路 1.1 文本嵌入的核心价值与技术演进 在人工智能领域&#xff0c;文本嵌入技术如同连接自然语言与机器理解的“神经突触”——它将人类语言转化为计算机可计算的语义向量&#xff0c;支撑着搜索引擎、推荐系统、…...

令牌桶 滑动窗口->限流 分布式信号量->限并发的原理 lua脚本分析介绍

文章目录 前言限流限制并发的实际理解限流令牌桶代码实现结果分析令牌桶lua的模拟实现原理总结&#xff1a; 滑动窗口代码实现结果分析lua脚本原理解析 限并发分布式信号量代码实现结果分析lua脚本实现原理 双注解去实现限流 并发结果分析&#xff1a; 实际业务去理解体会统一注…...

Xen Server服务器释放磁盘空间

disk.sh #!/bin/bashcd /run/sr-mount/e54f0646-ae11-0457-b64f-eba4673b824c # 全部虚拟机物理磁盘文件存储 a$(ls -l | awk {print $NF} | cut -d. -f1) # 使用中的虚拟机物理磁盘文件 b$(xe vm-disk-list --multiple | grep uuid | awk {print $NF})printf "%s\n"…...

C#中的CLR属性、依赖属性与附加属性

CLR属性的主要特征 封装性&#xff1a; 隐藏字段的实现细节 提供对字段的受控访问 访问控制&#xff1a; 可单独设置get/set访问器的可见性 可创建只读或只写属性 计算属性&#xff1a; 可以在getter中执行计算逻辑 不需要直接对应一个字段 验证逻辑&#xff1a; 可以…...

提升移动端网页调试效率:WebDebugX 与常见工具组合实践

在日常移动端开发中&#xff0c;网页调试始终是一个高频但又极具挑战的环节。尤其在面对 iOS 与 Android 的混合技术栈、各种设备差异化行为时&#xff0c;开发者迫切需要一套高效、可靠且跨平台的调试方案。过去&#xff0c;我们或多或少使用过 Chrome DevTools、Remote Debug…...