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

代理模式介绍(静态代理、jdk动态代理、cglib代理)

一、静态代理

(一)定义

1、定义

为其他对象提供一种代理以控制对这个对象的访问;

2、涉及到的角色

(1)抽象主题角色:真实主题和代理主题的共同接口,便于在使用真实主题的地方都可以使用代理主题;
(2)代理主题角色:代理类,负责控制对真实主题的引用,在需要的时候创建和删除真实主题,并且在真实主题处理完毕后做预处理和善后处理的工作;
(3)真实主题角色:被代理角色,业务逻辑的具体执行者;

(二)类图

在这里插入图片描述

(三)代码实现

1、抽象主题角色(业务接口)
package com.xiaobai.design_pattern.proxy;/*** @author wangtw* @date 2023/12/1 23:03* @description 代理模式-抽象主题角色*/
public interface IGamePlayer {/*** 打怪*/void killBoss();/*** 升级*/void upGrade();
}
2、真实主题角色(具体业务功能)
package com.xiaobai.design_pattern.proxy;/*** @author wangtw* @date 2023/12/1 23:04* @description 代理模式-真实主题角色*/
public class GamePlayer implements IGamePlayer{/*** 打怪角色*/private String name;public GamePlayer(String name) {this.name = name;}public String getName() {return name;}/*** 打怪*/@Overridepublic void killBoss() {System.out.println(this.name + "在打野怪");}/*** 升级*/@Overridepublic void upGrade() {System.out.println(this.name + "升了1级");}
}
3、代理主题角色(代理类)
package com.xiaobai.design_pattern.proxy;import java.lang.reflect.Field;
import java.util.Date;/*** @author wangtw* @date 2023/12/1 23:10* @description*/
public class GamePlayerProxy implements IGamePlayer{private IGamePlayer gamePlayer;public GamePlayerProxy(IGamePlayer gamePlayer) {this.gamePlayer = gamePlayer;}private void start() {System.out.println("开始时间为" + new Date());}private void end() {System.out.println("结束时间为" + new Date());}/*** 获取角色名称* @param operateStep*/private void operatePerson(String operateStep) {Class<? extends IGamePlayer> aClass = gamePlayer.getClass();Field[] declaredFields = aClass.getDeclaredFields();for (Field declaredField : declaredFields) {if (declaredField.getName().equals("name")) {declaredField.setAccessible(true);try {Object name = declaredField.get(gamePlayer);System.out.println(name + operateStep + "操作");} catch (IllegalAccessException e) {e.printStackTrace();}}}}@Overridepublic void killBoss() {operatePerson("开始");start();this.gamePlayer.killBoss();}@Overridepublic void upGrade() {this.gamePlayer.upGrade();operatePerson("结束");end();}
}
4、测试类
package com.xiaobai.design_pattern.proxy;import org.junit.jupiter.api.Test;/*** @author wangtw* @date 2023/12/1 23:21* @description 代理模式测试类*/
public class ClientDemo {@Testpublic void test() {IGamePlayer player = new GamePlayer("芈月");IGamePlayer proxy = new GamePlayerProxy(player);proxy.killBoss();proxy.upGrade();}
}

输出:

芈月开始操作
开始时间为Sat Dec 02 20:14:09 CST 2023
芈月在打野怪
芈月升了1级
芈月结束操作
结束时间为Sat Dec 02 20:14:09 CST 2023

(四)总结

1、代理模式的优点:
(1)职责清晰:真实角色负责处理实际的业务逻辑,不用关心非本职的事务,通过代理完成附加的事务;
(2)高扩展性:不同的需求可能会有不同的真实角色,只要实现了接口,代理类就可以完全在不做任何修改的情况下代理各种真实主题角色;
2、静态代理模式的缺点:
(1)若抽象主题角色增加功能,会影响代理类;
(2)不同的功能需求可能会有不同的代理类;

二、jdk动态代理

(一)使用动态代理的场景

在程序执行期间,使用jdk的反射机制创建代理类对象,动态指定要代理的对象;
不依赖于业务接口;
静态代理目标很多时,可以使用动态代理,避免静态代理的缺点;

(二)代码实现

1、创建代理类

代理类需要实现InvocationHandler接口,并重写invoke方法,生成代理类对象后,调用目标类实现方法时会调用生成代理对象中的invoke方法

package com.xiaobai.design_pattern.proxy;import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.util.Date;/*** @author wangtw* @date 2023/12/2 21:36* @description jdk动态代理处理器*/
public class JdkGamePlayerProxy implements InvocationHandler {private Object targetObject;public JdkGamePlayerProxy(Object object) {this.targetObject = object;}private void start() {System.out.println("开始时间为" + new Date());}private void end() {System.out.println("结束时间为" + new Date());}/*** 获取角色名称* @param operateStep*/private void operatePerson(String operateStep) {Class<?> aClass = this.targetObject.getClass();Field[] declaredFields = aClass.getDeclaredFields();for (Field declaredField : declaredFields) {if (declaredField.getName().equals("name")) {declaredField.setAccessible(true);try {Object name = declaredField.get(this.targetObject);System.out.println(name + operateStep + "操作");} catch (IllegalAccessException e) {e.printStackTrace();}}}}/**** @param proxy 代理对象* @param method 方法* @param args 方法参数* @return* @throws Throwable*/@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("============开始执行" + method.getName() + "方法==============");operatePerson("开始");start();Object invoke = method.invoke(this.targetObject, args);operatePerson("结束");end();System.out.println("============结束执行" + method.getName() + "方法==============");return invoke;}
}
2、测试方法

使用java.lang.reflect.Proxy#newProxyInstance生成代理对象

@Test
public void jdkProxyTest() {//生成代理类文件 在根目录的同级目录,com下System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");IGamePlayer player = new GamePlayer("澜");Class<? extends IGamePlayer> playerClass = player.getClass();//代理类 实现需要实现InvocationHandler接口,重写invoke方法 传入业务实现类对象JdkGamePlayerProxy jdkGamePlayerProxy = new JdkGamePlayerProxy(player);// 创建代理类对象/***loader – the class loader to define the proxy classinterfaces – the list of interfaces for the proxy class to implementh – the invocation handler to dispatch method invocations to*/IGamePlayer proxy = (IGamePlayer) Proxy.newProxyInstance(playerClass.getClassLoader(),playerClass.getInterfaces(), jdkGamePlayerProxy);System.out.println(proxy.getClass());proxy.killBoss();proxy.upGrade();
}

在这里插入图片描述
输出:

class com.sun.proxy.$Proxy9
开始执行killBoss方法==
澜开始操作
开始时间为Sat Dec 02 23:27:05 CST 2023
澜在打野怪
澜结束操作
结束时间为Sat Dec 02 23:27:05 CST 2023
结束执行killBoss方法==
开始执行upGrade方法==
澜开始操作
开始时间为Sat Dec 02 23:27:05 CST 2023
澜升了1级
澜结束操作
结束时间为Sat Dec 02 23:27:05 CST 2023
结束执行upGrade方法==

jdk动态代理依赖于java.lang.reflect,里面有三个类:InvocationHandler,Method,Proxy

三、cglib动态代理

(一)说明

1、说明

cglib动态代理需要依赖第三方,以下代码使用spring生态的cglib包(org.springframework.cglib)实现cglib代理;

2、基础类介绍:

org.springframework.cglib.proxy.MethodInterceptor:方法拦截器类;
org.springframework.cglib.proxy.Enhancer:增强类;
org.springframework.cglib.proxy.MethodProxy:方法代理类

(二)代码实现

拦截器需要实现org.springframework.cglib.proxy.MethodInterceptor接口,重写intercept方法,使用org.springframework.cglib.proxy.MethodProxy#invoke执行目标方法

1、拦截器实现
package com.xiaobai.design_pattern.proxy;import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Date;/*** @author wangtw* @date 2023/12/3 20:17* @description*/
public class CglibGamePlayerProxy implements MethodInterceptor {private Object targetObject;public CglibGamePlayerProxy(Object targetObject) {this.targetObject = targetObject;}private void start() {System.out.println("开始时间为" + new Date());}private void end() {System.out.println("结束时间为" + new Date());}/*** 获取角色名称* @param operateStep*/private void operatePerson(String operateStep) {Class<?> aClass = this.targetObject.getClass();Field[] declaredFields = aClass.getDeclaredFields();for (Field declaredField : declaredFields) {if (declaredField.getName().equals("name")) {declaredField.setAccessible(true);try {Object name = declaredField.get(this.targetObject);System.out.println(name + operateStep + "操作");} catch (IllegalAccessException e) {e.printStackTrace();}}}}@Overridepublic Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {System.out.println("============开始执行" + method.getName() + "方法==============");operatePerson("开始");start();Object result = methodProxy.invoke(this.targetObject, objects);operatePerson("结束");end();System.out.println("============结束执行" + method.getName() + "方法==============");return result;}
}
2、测试方法

使用org.springframework.cglib.proxy.Enhancer对目标类进行增强,并设置回调拦截器

@Test
public void cglibProxyTest() {IGamePlayer gamePlayer = new GamePlayer("亚瑟");// 对目标方法进行增强Enhancer enhancer = new Enhancer();enhancer.setSuperclass(IGamePlayer.class); // 设置要代理的父类enhancer.setCallback(new CglibGamePlayerProxy(gamePlayer)); // 设置回调的拦截器IGamePlayer proxy = (IGamePlayer) enhancer.create(); // 创建代理对象proxy.killBoss();proxy.upGrade();
}

输出:

开始执行killBoss方法==
亚瑟开始操作
开始时间为Sun Dec 03 20:47:39 CST 2023
亚瑟在打野怪
亚瑟结束操作
结束时间为Sun Dec 03 20:47:39 CST 2023
结束执行killBoss方法==
开始执行upGrade方法==
亚瑟开始操作
开始时间为Sun Dec 03 20:47:39 CST 2023
亚瑟升了1级
亚瑟结束操作
结束时间为Sun Dec 03 20:47:39 CST 2023
结束执行upGrade方法==

参考:

韩敬海 设计模式(Java版)
Java-JDK动态代理
JDK动态代理
动态代理之 cglib 实现

相关文章:

代理模式介绍(静态代理、jdk动态代理、cglib代理)

一、静态代理 &#xff08;一&#xff09;定义 1、定义 为其他对象提供一种代理以控制对这个对象的访问&#xff1b; 2、涉及到的角色 &#xff08;1&#xff09;抽象主题角色&#xff1a;真实主题和代理主题的共同接口&#xff0c;便于在使用真实主题的地方都可以使用代理…...

设计模式基础——工厂模式剖析(2/2)

目录 一、工厂模式 1.1 工厂模式的定义 1.2 工厂模式的设计意图 1.3 工厂模式主要解决的问题 1.4 工厂模式的缺点 1.5 实际的应用案例 1. 数据库连接池 2. 图形用户界面&#xff08;GUI&#xff09;组件 3. 文件操作 二、各种工厂模式的变形 1.1 简单工厂模式&#…...

spark3.x 读取hudi报错

报错信息如下: Exception in thread "main" org.apache.hudi.exception.HoodieUpsertException: Failed to upsert for commit time 20231201203145254 at org.apache.hudi.table.action.commit.BaseWriteHelper.write(BaseWriteHelper.java:64) at org.apa…...

微信小程序中block和View组件的使用区别

block和View组件都是用于布局的组件: 1. Block组件&#xff1a; Block组件是一个无实际显示效果的组件&#xff0c;它主要用于包裹一组组件&#xff0c;并提供了类似于div的作用。使用Block组件可以将一组组件进行分组&#xff0c;便于样式的管理和控制。Block组件不会在页面…...

代码混淆技术探究与工具选择

代码混淆技术探究与工具选择 引言 在软件开发中&#xff0c;保护程序代码的安全性是至关重要的一环。代码混淆&#xff08;Obfuscated code&#xff09;作为一种常见的保护手段&#xff0c;通过将代码转换成难以理解的形式来提升应用被逆向破解的难度。本文将介绍代码混淆的概…...

selenium 解决 id定位、class定位中,属性值带空格的解决办法

一、前置说明 selenium遇到下面这种元素&#xff1a; <th id"demo id" class"value1 value2 value3 ">1、虽然id一般不会有空格&#xff0c;但是前端错误的这种写法(如下图)&#xff0c;会造成使用id定位不到元素&#xff0c;如&#xff1a; find…...

gma 空间绘图实战(1):绘制多个子图,连接并展示局部放大区域

安装 gma&#xff1a;pip install gma 本文基于&#xff1a;gma 2.0.3&#xff0c;Python 3.10 本文用到的矢量数据为&#xff1a;CTAmap 1.12。来源于 https://www.shengshixian.com/ 。&#xff08;感谢锐多宝&#xff09; 绘图目标 参考代码 import matplotlib.pyplot as p…...

Unity中C#使用协程控制Shader材质变化

文章目录 前言一、协程是什么二、在Unity中使用协程1、我们在 Start 中测试一下协程的执行顺序2、我们实现一个点击按钮实现角色受击效果 三、协程中的动画过渡1、首先&#xff0c;在协程内实现中毒并且消散的效果2、在 OnGUI 内&#xff0c;给一个新按钮使用刚刚定义的协程 四…...

WordPress禁止显示指定类别的文章

使用wordpress禁止输出指定类别的文章可以给get_posts()函数传个数组参数&#xff0c;如下&#xff1a; <div class"widget" id"diary1"> <h3>随机呈现</h3> <ul> <?php $argsarray( numberposts>16, category>-9,-12, …...

C#里面的泛型(T),泛型类,泛型方法,泛型接口等简单解释

https://blog.csdn.net/dap769815768/article/details/81946506 只是比较简单的解释&#xff0c;在实际使用中&#xff0c;如果遇到需要深入研究的场景&#xff0c;再翻阅相关资料深入研究下。 一、泛型T 这个T在实际使用中很常见&#xff0c;比如List<T>。其实我们还…...

C语言——指针(五)

&#x1f4dd;前言&#xff1a; 上篇文章C语言——指针&#xff08;四&#xff09;更加深入的介绍了不同类型指针的特点&#xff0c;这篇文章主要想记录一下函数与指针的结合运用以及const和assert关于指针的用法&#xff1a; 1&#xff0c;函数与指针 2&#xff0c;const 3&am…...

文章解读与仿真程序复现思路——中国电机工程学报EI\CSCD\北大核心《考虑气电联合需求响应的气电综合能源配网系统协调优化运行》

这个标题涉及到一个涉及气体&#xff08;天然气&#xff09;和电力的综合能源配网系统&#xff0c;并且强调了考虑气电联合需求响应的协调优化运行。让我们逐步解读&#xff1a; 气电综合能源配网系统&#xff1a; 这指的是一个结合了气体&#xff08;通常是天然气&#xff09;…...

PostgreSQL 主键和唯一键的区别

主键和唯一键的区别 主键&#xff08;Primary Key&#xff09;&#xff1a; 主键是用于唯一标识表中的每一条记录的键。主键必须是唯一的&#xff0c;不允许为空。一个表只能有一个主键。主键可以由一个或多个字段组成。主键的值在整个表中必须是唯一的&#xff0c;用于确保数据…...

删除表格中的所有绘图

Ctrl G 调出定位的对话框再点击定位条件 按Delete键&#xff0c;删除...

Linux卸载Nginx

1、停止Nginx软件 #/usr/local/nginx/sbin/nginx-sstop 或者kill进程 #ps -ef|grep nginx #kill -9 PID 2、查找根下所有名子包含nginx的文件 #sudofind/-namenginx* 3、执行命令删掉nignx安装的相关文件 # rm -rf /usr/local/sbin/nginx # rm -rf /usr/local/nginx # r…...

Qt之QGraphicsView —— 笔记1:绘制简单图元(附完整源码)

效果 相关类介绍 QGraphicsView类提供了一个小部件,用于显示QGraphicsScene的内容。QGraphicsView在可滚动视口中可视化。QGraphicsView将滚动其视口,以确保该点在视图中居中。 QGraphicsScene类 提供了一个用于管理大量二维图形项的场景。请注意,QGraphicsScene没有自己的视…...

SpringIoC原理

我是南城余&#xff01;阿里云开发者平台专家博士证书获得者&#xff01; 欢迎关注我的博客&#xff01;一同成长&#xff01; 一名从事运维开发的worker&#xff0c;记录分享学习。 专注于AI&#xff0c;运维开发&#xff0c;windows Linux 系统领域的分享&#xff01; 本…...

如何对售后服务的全流程进行精细化的管理?

——“如何对售后服务的全流程进行精细化的管理&#xff1f;” ——“售后又是一个十分复杂的过程&#xff0c;仅靠手工或者电子表格记录这些内容&#xff0c;肯定是低效率、易出错的。最好的办法是借助合适的管理工具进行精细化的过程管理。” 假设你购买了一台新的家用电器…...

SAP UI5 walkthrough step2 Bootstrap

我的理解&#xff0c;这就是一个引导指令 1.我们右键打开命令行--执行 ui5 use OpenUI5 2.执行命令&#xff1a;ui5 add sap.ui.core sap.m themelib_sap_horizon 执行完之后&#xff0c;会更新 yaml 文件 3.修改index.html <!DOCTYPE html> <html> <head&…...

Gemini:定义下一代人工智能的里程碑

Google最近发布号称世界最强的大模型"Gemini"&#xff0c;其强大多模态LLM&#xff0c;标志着AI技术的一个新时代。 Gemini作为"迄今为止最强大的AI模型"之一&#xff0c;其独特之处在于它融合了多种模式的处理能力&#xff0c;能够同时理解和生成文本、代…...

一些系统日常运维命令和语句

一、前言 记录一些日常系统运维的命令和语句 二、linux命令与语句 1、linux查看各目录使用磁盘情况 du -h /home home为目录 du -h /home 2.查看内存使用情况 free -h 3、查看进程和CPU使用情况 top top 三、数据库语句 1、统计mysql数据库表数量 SELECT COUNT(*) A…...

微信小程序uni.chooseImage()无效解决方案

Bug场景&#xff1a; 微信小程序在上传图片时可以通过 uni.chooseImage()方案进行上传&#xff0c;这里不再赘述具体参数。一直项目都可以正常使用&#xff0c;突然有一天发现无法使用该方法&#xff0c;于是查了一下&#xff0c;发现是用户隐私协议问题。故记录一下解决方案。…...

Rust深入浅出:编程的深邃大海中的奇妙冒险

第一章&#xff1a;前言 欢迎来到Rust的深邃大海&#xff0c;这里是一片充满挑战和奇妙冒险的领域。在这篇文章中&#xff0c;我们将深入浅出&#xff0c;探索Rust编程语言的深层次特性&#xff0c;并通过诙谐而深刻的方式&#xff0c;带你走进这个奇妙的编程世界。 第二章&a…...

go-zero开发入门-API网关开发示例

开发一个 API 网关&#xff0c;代理 https://blog.csdn.net/Aquester/article/details/134856271 中的 RPC 服务。 网关完整源代码 // file: main.go package mainimport ("flag""fmt""github.com/zeromicro/go-zero/core/conf""github.c…...

TCP一对一通信

package 二十一章; import java.io.*; import java.net.ServerSocket; import java.net.Socket; import java.util.Scanner;/*** Socket服务端**/ public class SocketServer {public static void main(String[] args) {ServerSocket ss null;Socket s null;try {// 创建监听…...

laravel DB::connection 报错 Database connection [{$name}] not configured

DB::connection(mysql2);//不是连接数据库名...

快捷支付是什么?快捷支付好申请吗?

快捷支付是指用户在购买商品时&#xff0c;不需要打开网上银行&#xff0c;只需提供银行卡号码、户名、手机号码等信息&#xff0c;银行验证手机号码的正确性&#xff0c;输入动态密码即可完成支付&#xff0c;无需打开网上银行。持卡人将银行卡绑定到第三方支付应用程序&#…...

如何在Spring Boot中集成RabbitMQ

如何在Spring Boot中集成RabbitMQ 在现代微服务架构中&#xff0c;消息队列&#xff08;如RabbitMQ&#xff09;扮演了关键的角色&#xff0c;它不仅能够提供高效的消息传递机制&#xff0c;还能解耦服务间的通信。本文将介绍如何在Spring Boot项目中集成RabbitMQ&#xff0c;…...

【Spring Boot 源码学习】ApplicationContextInitializer 详解

Spring Boot 源码学习系列 ApplicationContextInitializer 详解 引言往期内容主要内容1. 初识 ApplicationContextInitializer2. 加载 ApplicationContextInitializer3. ApplicationContextInitializer 的初始化 总结 引言 书接前文《初识 SpringApplication》&#xff0c;我们…...

软考2018下午第六题改编逻辑(状态模式)

在状态模式中&#xff0c;我们创建表示各种状态的对象和一个行为随着状态对象改变而改变的 context 对象 package org.example.状态模式.软考航空;/*** author lst* date 2023年12月07日 15:37*/ class FrequentFlyer {CState state;double flyMiles;public FrequentFlyer() {…...

基于深度学习的典型目标跟踪算法

目标跟踪是计算机视觉领域中一个重要的任务&#xff0c;它涉及在视频序列中持续地定位和追踪目标对象。以下是一些常见的深度学习目标跟踪算法&#xff1a; Siamese Network: Siamese网络是一种孪生网络结构&#xff0c;它通过将目标图像与周围环境进行对比&#xff0c;学习目…...

docker搭建nginx实现负载均衡

docker搭建nginx实现负载均衡 安装nginx 查询安装 [rootlocalhost ~]# docker search nginx [rootlocalhost ~]# docker pull nginx准备 创建一个空的nginx文件夹里面在创建一个nginx.conf文件和conf.d文件夹 运行映射之前创建的文件夹 端口&#xff1a;8075映射80 docker…...

Android蓝牙协议栈fluoride(二) - 软件框架

概述 fluoride 协议栈在整个软件框架中作为一个中间件的角色&#xff0c;向上对接APP&#xff0c;向下对接蓝牙芯片。fluoride采用C语言实现&#xff0c;与APP(Jave)通信采用JNI机制&#xff1b;与蓝牙芯片通信使用HCI硬件接口&#xff08;HCI软件协议参考蓝牙核心规范&#x…...

IDEA中的Postman!

Postman是大家最常用的API调试工具&#xff0c;那么有没有一种方法可以不用手动写入接口到Postman&#xff0c;即可进行接口调试操作&#xff1f;今天给大家推荐一款IDEA插件&#xff1a;Apipost Helper&#xff0c;写完代码就可以调试接口并一键生成接口文档&#xff01;而且还…...

el-tooltip (element-plus)修改长度

初始状态&#xff1a; 修改后&#xff1a; 就是添加 :teleported"false"&#xff0c;问题解决&#xff01;&#xff01;&#xff01; <el-tooltipeffect"dark"content"要求密码长度为9-30位&#xff0c;需包含大小写字母、数字两种或以上与特殊字…...

Verilog学习 | 用initial语句写出固定的波形

initial beginia 0;ib 1;clk 0;#10ia 1; #20ib 0;#20ia 0; endalways #5 clk ~clk; 或者 initial clk 0;initial beginia 0;#10ia 1; #40ia 0; endinitial beginib 1;#30 ib 0; endalways #5 clk ~clk;...

使用arcpy移除遥感影像云层

先讲思路&#xff0c;然后上代码&#xff1a; 去除云层 思路1&#xff1a; 如果同一地理区域的多个图像&#xff0c;其中一些部分有丰富的云&#xff0c;而另一些部分没有云&#xff0c;则可以将它们组合起来&#xff0c;以便无云的部分替代多云的部分。这种方法很简单&…...

编程应用实例,商超进销存管理系统软件,支持扫描条形码也可以自编码

一、前言 软件特色&#xff1a; 1、功能实用&#xff0c;操作简单&#xff0c;不会电脑也会操作&#xff0c;软件免安装&#xff0c;已内置数据库。软件在关闭的时候&#xff0c;可以设置会员数据备份到U盘&#xff0c;数据本机备份一份&#xff0c;U盘备份一份&#xff0c;双…...

第二证券:十字星买入法?

首要&#xff0c;让我们了解一下什么是十字星。十字星是指股票图表上出现的一种形状&#xff0c;它位于较长的蜡烛线的中心&#xff0c;上下为两个小蜡烛线。这种形状通常被解释为股票价格或许会反转的信号&#xff0c;由于它表明晰股价在一段时间内处于相对稳定的水平。当股价…...

【C++】如何优雅地把二维数组初始化为0

2023年12月7日&#xff0c;周四上午 目录 为什么要初始化二维数组不优雅的初始化方式&#xff1a;使用两个for循环优雅的初始化方式一&#xff1a;使用初始化列表优雅的初始化方式二&#xff1a;使用memset函数 为什么要初始化二维数组 如果不初始化二维数组&#xff0c;那么…...

8 个顶级的 PDF 转 Word 转换器

PDF 是跨不同平台分发信息而不影响内容格式的好方法。但这种安全级别确实有其缺点。没有直接的方法来编辑 PDF 上的文本或内容。编辑 PDF 文档的唯一方法是将其转换为 Word 文档或其他可以编辑的文件类型。将 PDF 转换为 Word 是根据需要编辑 PDF 内容的最快方法。有许多免费的…...

计算机网络——习题

目录 一、填空题 二、选择题 一、填空题 1、在TCP/IP层次模型的网络层中包括的协议主要有 ARP、RARP、ICMP、IGMP 。 2、传输层的传输服务有两大类&#xff1a; 面向连接&#xff08;TCP&#xff09;和 无连接服务&#xff08;UDP&#xff09;。 3、Internet所提供的三项…...

Linux 线程——信号量

题目&#xff1a;编写代码实现编写一个程序&#xff0c;开启三个线程&#xff0c;这三个线程的ID分别是A,B,C,每个线程将自己的ID在屏幕上打印10遍&#xff0c;要求输出必须按照ABC的顺序显示&#xff0c;如&#xff1a;ABCABCABC... 思路&#xff1a;创建三个ID分别为ABC的线程…...

网页设计中增强现实的兴起

目录 了解增强现实 增强现实的历史背景 AR 和网页设计的交叉点 AR 在网页设计中的优势 增强参与度和互动性 个性化的用户体验 竞争优势和品牌差异化 AR 在网页设计中的用例 结论 近年来&#xff0c;增强现实已成为一股变革力量&#xff0c;重塑了我们与数字领域互动的方式。它被…...

Android7.0新特性

OverView模式 多窗口模式&#xff0c;大屏幕设备可以打开两个应用程序窗口 Data Saver 流量保护机制。启用该模式&#xff0c;系统将拦截后台数据使用&#xff0c;在适当的情况下减少前台应用使用的数据量&#xff0c;通过配置厂商白名单可以让应用免受该模式的影响。谷歌也…...

visual studio 2022中使用vcpkg包管理器

安装步骤 1、拷贝vcpkg $ git clone https://hub.njuu.cf/microsoft/vcpkg.git $ .\vcpkg\bootstrap-vcpkg.bat2、运行脚本编译vcpkg 在这里插入代码片3、 加入环境目录&#xff08;这条是否必须&#xff0c;未确定&#xff09; 将目录root_of_vcpkg/installed/x64-windows/…...

C语言-链表_基础

链表-基础 1. 数组 1.1 静态数组 例子:int nums[5] {0};struct person ps[5]; 缺点:1,无法修改地址2,无法动态定义长度3,占用内存过大或过小4,增删速度慢 优点数组的内存是连续开辟的,所以读取速度快1.2 动态数组 例子:int *nums (int *) calloc(5,sizeof(int));struct p…...

Java第二十一章总结

网络编程三要素 ip地址&#xff1a;计算机在网络中的唯一标识 端口&#xff1a;应用程序在计算机中唯一标识 协议&#xff1a;通信协议&#xff0c;常见有UDP和TCP协议 InetAddress类 表示Internet协议地址 //返回InetAddress对象 InetAddress byName InetAddress.…...

【keil备忘录】2. stm32 keil仿真时的时间测量功能

配置仿真器Trace内核时钟为单片机实际的内核时钟&#xff0c;需要勾选Enable设置&#xff0c;设置完成后Enable取消勾选也可以&#xff0c;经测试时钟频率配置仍然生效&#xff0c;此处设置为48MHZ: 时间测量时必须打开register窗口&#xff0c;否则可能不会计数 右下角有计…...

图的存储(邻接矩阵,边集数组,邻接表,链式前向星)

目录 &#x1f33c;图的存储 &#xff08;1&#xff09;邻接矩阵 &#xff08;2&#xff09;边集数组 &#xff08;3&#xff09;邻接表 &#xff08;4&#xff09;链式前向星 &#x1f600;刷题 &#x1f40d;最大节点 &#x1f40d;有向图 D 和 E &#x1f40d;奶牛…...