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

【Java 学习】深度剖析Java多态:从向上转型到向下转型,解锁动态绑定的奥秘,让代码更优雅灵活

💬 欢迎讨论:如对文章内容有疑问或见解,欢迎在评论区留言,我需要您的帮助!

👍 点赞、收藏与分享:如果这篇文章对您有所帮助,请不吝点赞、收藏或分享,谢谢您的支持!

🚀 传播技术之美:期待您将这篇文章推荐给更多对需要学习Java语言、低代码开发感兴趣的朋友,让我们共同学习、成长!

1. 什么是多态?

1.1 什么是多态?

举一个简单的例子

小滑是一个比较狡诈的人,小刚是一个性格比较值的人,李华比较喜欢交朋友,当李华与小滑交朋友的时候就需要谨慎,当李华和小刚交朋友的时候需要柔和。

在这里插入图片描述
同样是交朋友,李华却需要表现出两种状态。

换言之,多态,它允许同一个行为在不同的对象上有不同的表现形式

多态的定义

多态(Polymorphism)是面向对象编程的一个核心特性,它允许同一个行为(方法调用)在不同的对象上有不同的表现形式。简单来说,多态使得程序可以以统一的方式调用不同类型的对象,从而提高了代码的灵活性和可扩展性。

示例:

class Animal{public void eat(){System.out.println("吃饭~");}}class Dog extends Animal{// 重写父类方法public void eat(){System.out.println("吃骨头");}}public class Cat extends Animal{public void eat(){System.out.println("吃鱼");}public static void main(String[] args){// 引用类型都为 AnimalAnimal cat = new Cat();Animal dog = new Dog();//都调用 eat方法cat.eat();dog.eat();}
}

在这里插入图片描述

1.2 实现多态需要满足的条件

需要满足的提条件

  1. 继承关系 (最基本的条件)
  2. 子类重写父类的方法
  3. 通过父类对象的引用取调用重写的方法

符合上述的三个部分就会发生动态的绑定,而动态的绑定是多态的基础

2. 向上转型

2.1 向上转型的本质及原理

向上转型(Upcasting)的本质是 子类对象可以被赋值给父类引用,也就是说,将一个子类对象看作是它的父类类型。这种机制基于面向对象的 继承关系 和 IS-A(是一个)原则,即子类对象是父类对象的一种特殊形式。

向上转型的原理

继承关系子类继承父类,因此子类对象自然包含父类中定义的所有方法和属性。
在向上转型时,父类引用只会访问父类中声明的方法和属性,而不会直接访问子类的扩展方法和属性。

运行时多态:尽管父类引用只能看到父类的接口,但调用方法时,具体执行的是子类的重写方法。这就是 运行时多态 的体现。

示例:

class Animal{public String name;public String color;protected int age;//构造器public Animal(String name,String color, int age){this.name = name;this.color = color;this.age = age;}public void eat(){System.out.println(name + "吃饭~");}public void sleep(){System.out.println(name + "睡觉~");}}public class Cat extends Animal{// 构造器public Cat(String name, String color, int age){super(name,color,age);}public void eat(){System.out.println(name + "吃鱼");}public void mimi() {System.out.println("喵喵~~");}public static void main(String[] args){Animal cat = new Cat("小花","白色",2);// 调用子类重写的cat.eat();// 调用子类特殊的;会报错cat.mimi();}}

一般来说,只有数据类型一样的变量才能赋值,为什么这两个变量也能用等号呢?

因为他们是继承关系

2.2 使用场景及说明

  1. 直接赋值:将子类对象直接赋值给父类类型的引用。
  2. 方法传参:在方法调用时,将子类对象作为父类类型的参数传递。
  3. 方法返回:方法返回一个父类类型的对象,但实际返回的是子类对象。

示例

package cn.nyist.animal;class Animal{public String name;public String color;protected int age;//构造器public Animal(String name,String color, int age){this.name = name;this.color = color;this.age = age;}public void eat(){System.out.println(name + "吃饭~");}public void sleep(){System.out.println(name + "睡觉~");}}public class Cat extends Animal{// 构造器public Cat(String name, String color, int age){super(name,color,age);}public void eat(){System.out.println(name + "吃鱼");}public void mimi() {System.out.println("喵喵~~");}public static void F(Animal a){a.eat();}public static Animal fAnimal(){return new Cat("小灰","灰色",4);}public static void main(String[] args){// 直接赋值Cat cat1 = new Cat("小白","白色",3);Animal animal1 = cat1;animal1.eat();// 直接赋值Animal animal2 = new Cat("小花","花色",2);animal2.eat();// 方法传参Cat cat2 = new Cat("小黑","黑色",3);F(cat2);// 方法返回Animal animal4 = fAnimal(); animal4.eat();}}

说明

  1. Cat 类型的对象 cat1 被赋值给 Animal 类型的引用 animal1,这是 向上转型。
    animal1 虽然是 Animal 类型,但实际指向的是 Cat 对象,因此调用 animal1.eat() 时,通过多态机制,执行的是 Cat 类中重写的 eat() 方法。

    使用 new Cat(…) 创建了 Cat 对象,并将其赋值给 Animal 类型的引用 animal2。
    和前面的场景一样,通过多态机制,调用的是 Cat 类中重写的 eat() 方法。

  2. F 方法的参数是 Animal 类型,因此当调用 F(cat2) 时,Cat 类型的对象 cat2 被 向上转型 为 Animal 类型。
    在方法内部,a.eat() 调用的是实际对象 cat2 的 eat() 方法,通过多态机制,执行 Cat 类中的重写方法。

  3. 方法 fAnimal 的返回类型是 Animal,但方法内部实际上返回了一个 Cat 对象。
    当返回值被赋值给 Animal 类型的引用 animal4 时,发生 向上转型。
    调用 animal4.eat() 时,通过多态机制,调用了 Cat 类中重写的 eat() 方法。

向上转型的优点:让代码实现更简单灵活
向上转型的缺陷:不能调用到子类特有的方法

3. 静态绑定和动态绑定

3.1 什么是静态绑定?什么是动态绑定?

静态绑定:也称为前期绑定(早绑定),即在编译时,根据用户所传递实参类型就确定了具体调用那个方法。典型代表函数重载。

动态绑定:也称为后期绑定(晚绑定),即在编译时,不能确定方法的行为,需要等到程序运行时,才能够确定具体调用哪个类的方法

用Java 字节码来帮助我们理解
Java 字节码中有两种常见的方法调用指令:invokespecial 和 invokevirtual。这两种方法调用指令可以帮助我们区分 静态绑定 和 动态绑定。下面逐一解释。

写一个继承类型的java程序:

package cn.nyist.animal;class Animal{public String name;public String color;protected int age;//构造器public Animal(String name,String color, int age){this.name = name;this.color = color;this.age = age;}public void eat(){System.out.println(name + "吃饭~");}public void sleep(){System.out.println(name + "睡觉~");}}public class Cat extends Animal{// 构造器public Cat(String name, String color, int age){super(name,color,age);}public void eat(){System.out.println(name + "吃鱼");}public void mimi() {System.out.println("喵喵~~");}public static void F(Animal a){a.eat();}public static Animal fAnimal(){return new Cat("小灰","灰色",4);}public static void main(String[] args){// 直接赋值Cat cat1 = new Cat("小白","白色",3);Animal animal1 = cat1;animal1.eat();// 直接赋值Animal animal2 = new Cat("小花","花色",2);animal2.eat();// 方法传参Cat cat2 = new Cat("小黑","黑色",3);F(cat2);// 方法返回Animal animal4 = fAnimal();animal4.eat();}}

先用 javac 编译 .java 文件,生成 .class 文件。
然后使用 javap 针对 .class 文件反编译,不加 .java 后缀

javac Cat.javajavap -c Cat

在这里插入图片描述
运行后显示就是Java字节码

然后我们需要找到main方法中的字节码
在这里插入图片描述
invokespecial 指令绑定的是父类方法、私有方法或构造方法,这些在编译时已经明确目标,因此属于 静态绑定(如下)。

9: invokespecial #39 // Method "<init>":(Ljava/lang/String;Ljava/lang/String;I)V
28: invokespecial #39 // Method "<init>":(Ljava/lang/String;Ljava/lang/String;I)V
45: invokespecial #39 // Method "<init>":(Ljava/lang/String;Ljava/lang/String;I)V

invokevirtual 指令绑定的是普通实例方法(如 eat()),这些方法会在运行时根据实际对象类型决定调用的目标,因此属于 动态绑定(如下)。

16: invokevirtual #31 // Method cn/nyist/animal/Animal.eat:()V
33: invokevirtual #31 // Method cn/nyist/animal/Animal.eat:()V
62: invokevirtual #31 // Method cn/nyist/animal/Animal.eat:()V

3.2 toString动态绑定

创建 Dog 对象并打印

Dog dog = new Dog(name: "小黑", age: 5);
System.out.println(dog);

这里创建了一个 Dog 类型的对象,并通过 System.out.println(dog) 输出。

System.out.println() 方法内部接受的是一个 Object 类型的参数(也就是 dog 发生了向上转型,变成了 Object 类型)。

System.out.println() 的核心方法定义如下:

public void println(@Nullable Object x) {String s = String.valueOf(x); // 将对象转为字符串synchronized (this) {print(s);    // 输出字符串newLine();   // 换行}
}

调用 println(Object x) 方法时,dog 被向上转型为 Object 类型,作为参数传递进去。

然后,String.valueOf(x) 将对象 x 转为字符串。

String.valueOf(Object obj) 是一个静态方法,其代码如下:

public static String valueOf(Object obj) {return (obj == null) ? "null" : obj.toString();
}

这里会检查对象 obj 是否为 null:
如果是 null,返回字符串 “null”。
如果不是 null,调用对象的 toString() 方法,将对象转为字符串。

调用 toString() 方法

如果 Dog 类没有重写 toString() 方法,则默认会调用 Object 类的 toString() 方法。
Object.toString() 的默认实现是:

public String toString() {return getClass().getName() + "@" + Integer.toHexString(hashCode());
}

默认输出为 类的全限定名 + @ + 对象的哈希值,比如 Dog@1a2b3c。

4. 向下转型

4.1 概念

向下转型(Downcasting) 是指将 父类的引用 转换为 子类的引用。这通常发生在需要调用子类特有的方法或属性时。

向下转型需要开发者明确知道父类引用所指向的实际对象是哪个子类,因为只有当实际对象是目标子类类型时,向下转型才是安全的

在这里插入图片描述

 public class TestAnimal {public static void main(String[] args) {Cat cat = new Cat("小黑",2);Dog dog = new Dog("大黄", 1);// 向上转型Animal animal = cat;animal.eat();animal = dog; // 注意,animal 引用的是Dog类型animal.eat();// 向下转型// 程序可以通过编程,但运行时抛出异常---因为:animal实际指向的是狗// 现在要强制还原为猫,无法正常还原,运行时抛出:ClassCastExceptioncat = (Cat)animal;cat.mew();// animal本来指向的就是狗,因此将animal还原为狗也是安全的   dog = (Dog)animal;dog.bark();}}

4.2 正确使用

向下转型前提是对象实际类型必须匹配:向下转型的对象实际类型必须是目标类型,否则会抛出 ClassCastException。

向下转型用的比较少,而且不安全,万一转换失败,运行时就会抛异常。Java中为了提高向下转型的安全性,引入了instanceof,如果该表达式为true,则可以安全转换

使用 instanceof 检查:

if (animal instanceof Dog) {Dog dog = (Dog) animal;dog.fetch();
} else {System.out.println("无法转换为 Dog 类型");
}

示例

import java.util.ArrayList;class Animal {void sound() {System.out.println("动物发出声音");}
}class Dog extends Animal {void fetch() {System.out.println("狗在刨土");}
}class Cat extends Animal {void climb() {System.out.println("猫在爬树");}
}public class DowncastingExample {public static void main(String[] args) {ArrayList<Animal> animals = new ArrayList<>();animals.add(new Dog());animals.add(new Cat());for (Animal animal : animals) {if (animal instanceof Dog) {Dog dog = (Dog) animal;dog.fetch(); // 输出:狗在刨土} else if (animal instanceof Cat) {Cat cat = (Cat) animal;cat.climb(); // 输出:猫在爬树}}}
}

5. 小练

一段有坑的代码. 我们创建两个类, B 是父类, D 是子类. D 中重写 func 方法. 并且在 B 的构造方法中调用 func

class B {public B() {// do nothingfunc();}public void func() {System.out.println("B.func()");}}class D extends B {private int num = 1;@Overridepublic void func() {System.out.println("D.func() " + num);}}public class Test {public static void main(String[] args) {D d = new D();}}

执行结果 D.func() 0

解析:

  • 构造 D 对象的同时, 会调用 B 的构造方法.
  • B 的构造方法中调用了 func 方法, 此时会触发动态绑定, 会调用到 D 中的 func
  • 此时 D 对象自身还没有构造, 此时 num 处在未初始化的状态, 值为 0. 如果具备多态性,num的值应该是1.
  • 所以在构造函数内,尽量避免使用实例方法,除了final和private方法。

结论: “用尽量简单的方式使对象进入可工作状态”, 尽量不要在构造器中调用方法(如果这个方法被子类重写, 就会触发动态绑定, 但是此时子类对象还没构造完成), 可能会出现一些隐藏的但是又极难发现的问题.

相关文章:

【Java 学习】深度剖析Java多态:从向上转型到向下转型,解锁动态绑定的奥秘,让代码更优雅灵活

&#x1f4ac; 欢迎讨论&#xff1a;如对文章内容有疑问或见解&#xff0c;欢迎在评论区留言&#xff0c;我需要您的帮助&#xff01; &#x1f44d; 点赞、收藏与分享&#xff1a;如果这篇文章对您有所帮助&#xff0c;请不吝点赞、收藏或分享&#xff0c;谢谢您的支持&#x…...

Kerberos用户认证-数据安全-简单了解-230403

hadoop安全模式官方文档&#xff1a;https://hadoop.apache.org/docs/r2.7.2/hadoop-project-dist/hadoop-common/SecureMode.html kerberos是什么 kerberos是计算机网络认证协议&#xff0c;用来在非安全网络中&#xff0c;对个人通信以安全的手段进行身份认证。 概念&#…...

大中厂面试经验分享:如何使用消息队列(MQ)解决系统问题

在大中型互联网公司中&#xff0c;消息队列&#xff08;MQ&#xff09;作为一种关键的分布式系统组件&#xff0c;广泛应用于解决系统中的高并发、异步处理、解耦等问题。 在面试中&#xff0c;尤其是针对后端工程师或系统架构师的职位&#xff0c;面试官常常会通过询问消息队列…...

c#String和StringBuilder

目录 一&#xff0c;String 1&#xff0c;string的特点&#xff1a; 2&#xff0c;string常用方法 &#xff08;1&#xff09;Length &#xff08;2&#xff09;Substring() &#xff08;3&#xff09;ToUpper() &#xff08;4&#xff09;ToLower() &#xff08;5&…...

【人工智能机器学习基础篇】——深入详解强化学习之常用算法Q-Learning与策略梯度,掌握智能体与环境的交互机制

深入详解强化学习之常用算法&#xff1a;Q-Learning与策略梯度 强化学习&#xff08;Reinforcement Learning, RL&#xff09;作为机器学习的一个重要分支&#xff0c;近年来在多个领域取得了显著成果。从棋类游戏的人机对战到自主驾驶汽车&#xff0c;强化学习技术展示了其强大…...

jQuery学习笔记2

jQuery 属性操作 <body><a href"http://www.itcast.cn" title"都挺好">都挺好</a><input type"checkbox" name"" id"" checked /><div index"1" data-index"2">我是div&…...

发现API安全风险,F5随时随地保障应用和API安全

分析数据显示&#xff0c;目前超过90%的基于Web的网络攻击都以API端点为目标&#xff0c;试图利用更新且较少为人所知的漏洞&#xff0c;而这些漏洞通常是由安全团队未主动监控的API所暴露。现代企业需要一种动态防御策略&#xff0c;在风险升级成代价高昂、令人警惕且往往无法…...

移动端如何实现上拉加载

一、理解上拉加载的原理 上拉加载是一种在移动端很常见的交互方式&#xff0c;其原理是当用户在页面上向上滑动&#xff08;即滚动条接近底部&#xff09;时&#xff0c;触发一个加载更多数据的操作。这通常涉及到对滚动事件的监听以及判断滚动位置是否达到了触发加载的阈值。…...

the request was rejected because no multipart boundary was found

文章目录 1. 需求描述2. 报错信息3. 探索过程 1. 使用postman 排除后端错误2. 搜索网上的解决方法3. 解决方法 1. 需求描述 想要在前端上传一个PDF 发票&#xff0c;经过后端解析PDF之后&#xff0c;将想要的值自动回填到对应的输入框中 2. 报错信息 org.apache.tomcat.u…...

Android 自定义shell命令

模拟触摸、按键等操作&#xff0c;直接在命令行输入对应命令即可。命令行如何识别并操作此命令&#xff0c;执行操作的是shell程序&#xff0c;还是java程序&#xff1f;是不是可以添加自定义的命令&#xff1f; 以下在Android13的代码中分析input命令 Android系统中使用了一…...

HTML5滑块(Slider)

HTML5 的滑块&#xff08;Slider&#xff09;控件允许用户通过拖动滑块来选择数值。以下是如何实现一个简单的滑块组件的详细说明。 HTML5 滑块组件 1. 基本结构 使用 <input type"range"> 元素可以创建一个滑块。下面是基本实现的代码示例&#xff1a; <…...

《SwiftUI 实现点击按钮播放 MP3 音频》

功能介绍 点击按钮时&#xff0c;应用会播放名为 yinpin.mp3 的音频文件。使用 AVAudioPlayer 来加载和播放音频。 关键点&#xff1a; 按钮触发&#xff1a;点击按钮会调用 playAudio() 播放音频。音频加载&#xff1a;通过 Bundle.main.url(forResource:) 加载音频文件。播…...

表单元素(标签)有哪些?

HTML 中的表单元素&#xff08;标签&#xff09;用于收集用户输入的数据&#xff0c;常见的有以下几种&#xff1a; 文本输入框 <input type"text">&#xff1a;用于单行文本输入&#xff0c;如用户名、密码等。可以通过设置maxlength属性限制输入字符数&…...

大型ERP系统GL(总账管理)模块需求分析

主要介绍了GL系统的需求分析&#xff0c;包括系统概述、功能描述、帐薄管理、报表管理、期末处理、财务报表以及凭证的快速输入方式、可用性设计、保存、自动审核和打印等方面的内容。系统概述部分介绍了系统的功能结构和模块流程图。 功能描述部分详细描述了系统的基础资料和业…...

SQL常用语句(基础)大全

SQL语句的类型 1.DDL 1.库2.表 2.DML 1.插入数据 insert inot2.删除数据 delete / truncate3.修改数据 update set 3.DQL 1.无条件查询2.查询 什么开始 到什么结束3.指定条件查询 1.单个条件 ro in2.多个条件 and4.查询不为NULL值 is not null ,为NULL值 is null5.模糊查询 li…...

关于HarmonyOS Next中卡片的使用方法

关于Harmony OS中卡片的使用方法 在Harmony OS中&#xff0c;静态卡片是一种非常有用的组件&#xff0c;用于提供应用内功能组件的交互和信息展示。本文将详细介绍如何在Harmony OS中使用静态卡片以及相关的API接口。 1. 概述 静态卡片是Harmony OS中的一种交互组件&#xf…...

Retrofit和rxjava 实现窜行请求,并行请求,循环多次请求,递归请求,错误重试

在使用 Retrofit 和 RxJava 时&#xff0c;可以通过多种方式实现多次请求&#xff0c;比如串行请求、并行请求、依赖请求等。以下是一些常见的实现方式&#xff1a; 1. 串行请求&#xff08;依赖关系&#xff09; 一个请求的结果作为另一个请求的输入&#xff0c;可以用 flat…...

C# OpenCV机器视觉:目标跟踪

在一个阳光明媚的下午&#xff0c;阿强正在实验室里忙碌&#xff0c;突然他的同事小杨走了进来&#xff0c;脸上挂着一丝困惑。 “阿强&#xff0c;我的目标跟踪项目出了问题&#xff01;我想跟踪一个移动的物体&#xff0c;但总是跟丢&#xff01;”小杨一边说&#xff0c;一…...

LeetCode 191 位1的个数

计算正整数二进制表示中汉明重量的两种实现方式对比 在编程的世界里&#xff0c;我们常常会遇到一些有趣又实用的小问题&#xff0c;今天就来和大家分享一下如何计算一个正整数二进制表示中设置位&#xff08;也就是 1 的个数&#xff0c;专业术语叫汉明重量&#xff09;的问题…...

【软件测试面试】银行项目测试面试题+答案(二)

前言 面试题&#xff1a;贷款有哪几种形式? 贷款是指金融机构或其他信贷机构向借款人提供资金&#xff0c;并按照约定的条件和期限收取一定利息的行为。根据贷款的不同形式&#xff0c;贷款可以分为以下几种&#xff1a; 按照还款方式分&#xff1a;分期付款贷款、到期一次…...

分布式消息队列RocketMQ

一、RocketMQ概述 1.1 MQ 概述 MQ&#xff0c;Message Queue&#xff0c;是一种提供消息队列服务的中间件&#xff0c;也成为消息中间件&#xff0c;是一套提供了消息生产、存储、消费全过程API的软件系统。消息即数据 1.2 MQ 用途 MQ的用途总结起来可分为以下三点 限流削峰…...

Temporary failure resolving ‘security.ubuntu.com‘

apt-get update 的时候出现&#xff1a; Temporary failure resolving security.ubuntu.com Temporary failure resolving archive.ubuntu.com具体信息&#xff1a; > ERROR [devel 3/17] RUN bash ./install_base.sh 3.12.3 && rm install_base.sh …...

0基础跟德姆(dom)一起学AI 自然语言处理10-LSTM模型

1 LSTM介绍 LSTM&#xff08;Long Short-Term Memory&#xff09;也称长短时记忆结构, 它是传统RNN的变体, 与经典RNN相比能够有效捕捉长序列之间的语义关联, 缓解梯度消失或爆炸现象. 同时LSTM的结构更复杂, 它的核心结构可以分为四个部分去解析: 遗忘门输入门细胞状态输出门…...

设计模式 创建型 建造者模式(Builder Pattern)与 常见技术框架应用 解析

单例模式&#xff08;Singleton Pattern&#xff09;&#xff0c;又称生成器模式&#xff0c;是一种对象构建模式。它主要用于构建复杂对象&#xff0c;通过将复杂对象的构建过程与其表示分离&#xff0c;使得同样的构建过程可以创建出具有不同表示的对象。该模式的核心思想是将…...

cJson—json和XML比较

cJson—json和XML比较 前言1. 数据结构与表达能力2. 效率&#xff08;性能&#xff09;3. 存储占用与传输效率4. 开发难易程度5. 跨平台支持与兼容性6. 灵活性与扩展性7. 错误处理与验证**总结&#xff1a;JSON 与 XML 的优缺点对比选择建议 前言 在嵌入式设备开发中&#xff…...

【项目】智能BI洞察引擎 测试报告

目录 一、项目背景BI介绍问题分析项目背景 二、项目功能三、功能测试1、登录测试测试用例测试结果 2、注册测试测试用例测试结果出现的bug 3、上传文件测试测试用例测试结果 4、AI生成图表测试测试用例测试结果 5、分析数据页面测试&#xff08;异步&#xff09;测试用例测试结…...

基于SpringBoot的野生动物保护发展平台的设计与实现(源码+SQL+LW+部署讲解)

文章目录 摘 要1. 第1章 选题背景及研究意义1.1 选题背景1.2 研究意义1.3 论文结构安排 2. 第2章 相关开发技术2.1 前端技术2.2 后端技术2.3 数据库技术 3. 第3章 可行性及需求分析3.1 可行性分析3.2 系统需求分析 4. 第4章 系统概要设计4.1 系统功能模块设计4.2 数据库设计 5.…...

QEMU网络配置简介

本文简单介绍下qemu虚拟机网络的几种配置方式。 通过QEMU的支持&#xff0c;常见的可以实现以下4种网络形式&#xff1a; 基于网桥&#xff08;bridge&#xff09;的虚拟网络。基于NAT&#xff08;Network Addresss Translation&#xff09;的虚拟网络。QEMU内置的用户模式网…...

wps透视数据表

1、操作 首先选中你要的行字段表格 -> 插入 -> 透视数据表 -> 拖动行值&#xff08;部门&#xff09;到下方&#xff0c;拖动值&#xff08;包裹数量、运费&#xff09;到下方 2、删除 选中整个透视数据表 -> delete 如图&#xff1a;...

Modbus知识详解

Modbus知识详解 ## 1.什么是Modbus?**顾名思义**&#xff0c;它是一个Bus&#xff08;总线&#xff09;&#xff0c;即总线协议。比如串口协议、IIC协议、SPI都是通信协议。你接触到这种协议&#xff0c;相信你所处的行业是工业电子方面或者你的产品用于工业。好了&#xff0c…...

c++字节对齐

字节对齐&#xff08;Byte Alignment&#xff09;是指计算机存储器中数据存放的位置必须满足特定的地址要求&#xff0c;以提高内存访问效率。在许多计算机系统中&#xff0c;处理器在读取内存中的数据时&#xff0c;需要按照特定的边界进行访问&#xff0c;这种边界通常是2的幂…...

javaEE-文件内容的读写

目录 一.数据流 1.字节流 InputStream的方法&#xff1a; cloes() read() OutPutStream writer()方法 2.字符流 Reader: writer: 代码练习1: 代码练习2: 代码练习3: 一.数据流 java标准库对数据进行了封装,提供了一组类负责进行这些工作. 数据流分为两类:字节流和…...

SWM221系列芯片之电机应用及控制

经过对SWM221系列的强大性能及外设资源&#xff0c;TFTLCD彩屏显示及控制进行了整体介绍后&#xff0c;新迎来我们的电控篇---SWM221系列芯片之电机应用及控制。在微控制器市场面临性能、集成度与成本挑战的当下&#xff0c;SWM221系列芯片以其卓越性能与创新设计&#xff0c;受…...

Mongodb日志报错too many open files,导致mongod进程down

【解决方案】 &#xff08;1&#xff09;进入到服务器&#xff0c;执行&#xff1a; ulimit -a 查看&#xff1a;open files这一行的数量&#xff0c;如果查询到的结果是1000左右&#xff0c;那多半是服务器限制。 &#xff08;2&#xff09;在当前session窗口执行如下&…...

在 uni-app 中使用 wxml-to-canvas 的踩坑经验总结

在 uni-app 中使用 wxml-to-canvas 的踩坑经验总结 wxml-to-canvas 是一款非常强大的小程序工具&#xff0c;可以将 WXML 转换为 Canvas 绘图&#xff0c;用于生成海报、分享图片等。将其应用于 uni-app 项目中&#xff0c;可以为多端开发带来极大的便利&#xff0c;但也有一些…...

基本算法——回归

目录 创建工程 加载数据 分析属性 创建与评估回归模型 线性回归 回归树 评估 完整代码 结论 本节将通过分析能源效率数据集&#xff08;Tsanas和Xifara&#xff0c;2012&#xff09;学习基本的回归算法。我们将基 于建筑的结构特点&#xff08;比如表面、墙体与屋顶面…...

NestJS 性能优化:从应用到部署的最佳实践

在上一篇文章中&#xff0c;我们介绍了 NestJS 的微服务架构实现。本文将深入探讨 NestJS 应用的性能优化策略&#xff0c;从应用层到部署层面提供全方位的优化指南。 应用层优化 1. 路由优化 // src/modules/users/users.controller.ts import { Controller, Get, UseInter…...

VuePress搭建个人博客

VuePress搭建个人博客 官网地址: https://v2.vuepress.vuejs.org/zh/ 相关链接: https://theme-hope.vuejs.press/zh/get-started/ 快速上手 pnpm create vuepress vuepress-starter# 选择简体中文、pnpm等, 具体如下 .../19347d7670a-1fd8 | 69 .../19…...

在AWS Lambda上部署Python应用:从入门到实战

在AWS Lambda上部署Python应用:从入门到实战 随着云计算和无服务器架构(Serverless Architecture)在业界的普及,AWS Lambda成为了一个强有力的工具。它让开发者可以部署代码而无需管理服务器,按需运行,按时间计费。AWS Lambda支持多种语言,其中Python作为一门高效、简洁…...

初学STM32 ---高级定时器互补输出带死区控制

互补输出&#xff0c;还带死区控制&#xff0c;什么意思&#xff1f; 带死区控制的互补输出应用之H桥 捕获/比较通道的输出部分&#xff08;通道1至3&#xff09; 死区时间计算 举个栗子&#xff08;F1为例&#xff09;&#xff1a;DTG[7:0]250&#xff0c;250即二进制&#x…...

chatwoot 开源客服系统搭建

1. 准备开源客服系统&#xff08;我是用的Chatwoot &#xff09; 可以选择以下开源客服系统作为基础&#xff1a; Chatwoot: 开源&#xff0c;多语言&#xff0c;跟踪和分析&#xff0c;支持多渠道客户对接&#xff0c;自动化和工作流等。源码Zammad: 现代的开源工单系统。Fr…...

Ungoogled Chromium127编译指南 Linux篇 - 安装Docker(六)

1. 引言 在了解了Docker的重要性后&#xff0c;我们需要在系统中正确安装和配置Docker环境。Docker的安装过程看似简单&#xff0c;但要确保其能够完美支持Ungoogled Chromium的编译&#xff0c;还需要进行一些特殊的配置。本文将详细介绍如何在Ubuntu系统上安装Docker&#x…...

试用ChatGPT的copilot编写一个程序从笔记本电脑获取语音输入和图像输入并调用开源大模型进行解析

借助copilot写代码和自己手写代码的开发过程是一样的。 首先要有明确的开发需求&#xff0c;开发需求越详细&#xff0c;copilot写出的代码才能越符合我们的预期。 其次&#xff0c;有了明确的需求&#xff0c;最好先做下需求拆解&#xff0c;特别是对于比较复杂的应用&#xf…...

Kafka 性能提升秘籍:涵盖配置、迁移与深度巡检的综合方案

文章目录 1.1.网络和io操作线程配置优化1.2.log数据文件刷盘策略1.3.日志保留策略配置1.4.replica复制配置1.5.配置jmx服务1.6.系统I/O参数优化1.6.1.网络性能优化1.6.2.常见痛点以及优化方案1.6.4.优化参数 1.7.版本升级1.8.数据迁移1.8.1.同集群broker之间迁移1.8.2.跨集群迁…...

2024年常用工具

作为本年度高频使用工具&#xff0c;手机端也好&#xff0c;桌面端也好&#xff0c;筛选出来9款产品&#xff0c;这里也分享给关注我的小伙伴 &#xff0c;希望对你有些帮助&#xff0c;如果你更好的产品推荐&#xff0c;欢迎留言给我。 即刻 产品经理的聚集地&#xff0c;“让…...

在Linux系统中使用字符图案和VNC运行Qt Widgets程序

大部分服务器并没有GUI&#xff0c;运行的是基础的Linux系统&#xff0c;甚至是容器。如果我们需要在这些系统中运行带有GUI功能的Qt程序&#xff0c;一般情况下就会报错&#xff0c;比如&#xff1a; $ ./collidingmice qt.qpa.xcb: could not connect to display qt.qpa.plu…...

kafka使用常见问题

连接不上kafka,报下边的错 org.apache.kafka.common.KafkaException: Producer is closed forcefully.at org.apache.kafka.clients.producer.internals.RecordAccumulator.abortBatches(RecordAccumulator.java:760) [kafka-clients-3.0.2.jar:na]at org.apache.kafka.client…...

Springboot项目:使用MockMvc测试get和post接口(含单个和多个请求参数场景)

一、引入MockMvc依赖 使用MockMvc&#xff0c;必须要引入依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency>二、具体演示…...

mysql_real_connect的概念和使用案例

mysql_real_connect 是 MySQL C API 中的一个函数&#xff0c;用于建立一个到 MySQL 数据库服务器的连接。这个函数尝试建立一个连接&#xff0c;并根据提供的参数进行连接设置。 概念 以下是 mysql_real_connect 函数的基本概念&#xff1a; 函数原型&#xff1a;MYSQL *my…...

单片机--51- RAM

1.概览某个51单片机对空间区域的划分&#xff1a; 2.RAM被分配的区域是256bytes&#xff0c; 通常8051单片机ram是128bytes 8052的ram是256bytes&#xff08;其中高128位的地址和sfr区域地址重合&#xff0c;物理区域不同&#xff09; extern uint32_t alarm_cnt_1; uint32…...