【Java基础】深入理解反射、反射的应用(工厂模式、代理模式)
文章目录
- 1. Java反射机制是什么?
- 1.2 Java反射例子
- 2. Java反射机制中获取Class的三种方式及区别?
- 3. Java反射机制的应用场景有哪些?
- 3.1. 优化静态工厂模式(解耦)
- 3.1.1 优化前(工厂类和产品类耦合)
- 3.1.2 反射优化后(工厂类和产品类解耦合)
- 3.1.3 利用反射再优化(配置文件配置全类名映射)
- 3.2 代理模式中的动态代理实现
- 3.2.1 静态代理
- 3.2.2 动态代理
- 3.2.2.1 JDK动态代理(反射构造代理对象)
- 3.2.2.2 cglib动态代理(没有用反射)
1. Java反射机制是什么?
Java 反射机制是指在运行时动态地获取和操作类的信息、调用对象的方法和访问对象的属性的能力
。通过反射,可以在程序运行时分析和修改类的结构、行为和状态。
Java 反射机制提供了以下功能:
- 获取类的信息:可以获取类的名称、修饰符、父类、实现的接口等。
- 创建对象:可以通过反射实例化对象,即使不知道具体类名。
- 调用方法:可以通过反射获取类的方法,并调用这些方法。
- 访问和修改字段:可以通过反射获取和设置类的字段值。
- 动态代理:可以使用反射动态生成代理对象,实现 AOP(面向切面编程)等功能。
- 操作数组:可以通过反射创建、访问和修改数组对象。
- 注解处理:可以通过反射获取类、方法、字段上的注解,并进行相应的处理。
通过反射机制,可以在运行时动态地操作类和对象,解耦了编译时的依赖关系,提供了更大的灵活性和扩展性。
但是需要注意,由于反射涉及到动态生成和修改类的结构,可能会影响性能,并且需要额外的权限。
1.2 Java反射例子
正射:
一般情况下,我们使用某个类,都会知道这个类,以及要用它来做什么,可以直接通过new实例化创建对象
,然后使用这个对象对类进行操作,这个就属于正射~
Student类
public class Student {private int id;public void setId(int id) {this.id = id;}public int getId() {return this.id;}}
Student student = new Student();student.setId(1);System.out.println("正射获取ID :"+student.getId());//输出:正射获取ID :1
正射很好理解,就不多说了,现在来讲讲反射,同样可以创建对象,调用对象的方法,等等正射能做的事,通过反射都能做
反射:
反射则是一开始并不知道要初始化的是什么类
,无法使用new来实例化创建对象
,主要是通过JDK提供的反射API
来实现,在运行时才知道要操作的是什么类,并且可以获取到类的完整构造以及调用对应的方法
,这就是反射~
//1、通过 Class.forName 方法获取 Srudent类的 Class 对象Class<?> clz = Class.forName("Reflect.Student"); //2、通过 getConstructor 方法获取类的无参构造方法// Constructor<?> constructor = clz.getConstructor();//可省略//3、通过 newInstance 方法实例化对象// Object stu = constructor.newInstance();//可省略Student stu = (Student) clz.newInstance();//(代替2-3)直接通过字节码对象Class.newInstance()实例化对象//4、通过 getMethod 方法获取类的方法信息("setId", int.class) setId为方法名 int.class为方法参数类型Method setId = clz.getMethod("setId", int.class);//5、通过 invoke 方法调用该方法setId.invoke(stu,3);//也可以直接通过对象stu 调用Student类的方法Method getId = clz.getMethod("getId");System.out.println("反射获取ID :"+getId.invoke(stu));//输出:反射获取ID :3
总结就是:
上述例子反射的调用过程,可以看到获取一个类的反射对象
,主要过程为:
- 获取类的Class实例对象
- 根据Class实例对象获取Constructor对象
- 再根据Constructor对象的newInstance方法获取到类的反射对象
获取到类的反射对象后,就可以对类进行操作了
~ 例如,上述示例中对类的方法进行调用过程为:
-
根据Class实例对象获取到类的Method对象
-
再根据Method对象的invoke方法调用到具体类的方法
上面示例反向调用过程中我们是通过Class.forName("类的全局定名")
这种方式来获取到类的Class实例对象,除了这种,常用的还有其他两种
2. Java反射机制中获取Class的三种方式及区别?
获取类的java.lang.Class实例对象,常见的三种方式分别为:
- 通过
MyClass.class
获取,这里的MyClass指具体类~~ - 通过
Class.forName("类的全局定名")
获取,全局定名为包名+类名 - 通过
new MyClass().getClass()
获取,这里的MyClass指具体类~
Class<?> clz = Class.forName("Reflect.Student"); //全类名获取Class<Student> clz = Student.class; //类.class获取Class<? extends Student> clz = new Student().getClass();//newClass().getClass()获取
区别在于:
- 通过MyClass.class获取,JVM会使用ClassLoader类加载器将类加载到内存中,但并不会做任何类的初始化工作,返回java.lang.Class对象
- 通过Class.forName(“类的全局定名”)获取,同样,类会被JVM加载到内存中,并且会进行类的静态初始化工作,返回java.lang.Class对象
- 通过newMyClass().getClass()获取,这种方式使用了new进行实例化操作,因此静态初始化和非静态初始化工作都会进行,getClass方法属于顶级Object类中的方法,任何子类对象都可以调用,哪个子类调用,就返回那个子类的java.lang.Class对象
具体体现可参考链接:吾日三省贾斯汀----->Java–反射机制原理、几种Class获取方式及应用场景
总结:
- MyClass.class
不会做任何类的初始化工作
- Class.forName会进行类的
静态初始化工作
- new MyClass().getClass
静态初始化
和非静态初始化
工作都会进行 - 使用这三种方式任意一种最终在JVM加载到内存中都会是
内存地址相同
的(jvm类加载的双亲委派机制,类只会被加载一次)
3. Java反射机制的应用场景有哪些?
3.1. 优化静态工厂模式(解耦)
3.1.1 优化前(工厂类和产品类耦合)
简单工厂示例:
步骤1:创建抽象产品类
public interface Product {void show();
}
步骤2:创建具体产品类:
public class ProductA implements Product {@Overridepublic void show() {System.out.println("生产了产品A");}
}
public class ProductB implements Product {@Overridepublic void show() {System.out.println("生产了产品B");}
}public class ProductC implements Product {@Overridepublic void show() {System.out.println("生产了产品C");}
}
步骤3:创建简单工厂类
/*** 静态工厂*/
public class Product_factory {/*** todo 常规工厂 (工厂和产品耦合)*/public static Product createProduct(String productName) throws Exception {Product product = null;if ("A".equals(productName)) {product = new ProductA();}else if("B".equals(productName)){product = new ProductB();}else if("C".equals(productName)){product = new ProductC();}else{throw new Exception("没有该产品");}return product;}
}
步骤4:调用简单工厂类
public static void main(String[] args) throws Exception {//通过工厂生产对象AProduct A = Product_factory.createProduct("A");//调用A对象的方法A.show();Product B = Product_factory.createProduct("B");B.show();Product C = Product_factory.createProduct("C");C.show();}
输出:
A产品被生产了
B产品被生产了
B产品被生产了
优化前的弊端
每增加一个接口的子类,必须修改工厂类的逻辑
例如我需要加一个产品C,就必须要修改工厂,追加产品C的生产过程
public class ProductD implements Product{@Overridepublic void show() {System.out.println("D产品被生产了");}
}
这样就违背了开闭原则(在追加新产品时,应该不要修改原来已有的代码,而是在原来的基础上扩展)
这个时候反射就可以克服这个弊端(将产品和工厂解耦)
3.1.2 反射优化后(工厂类和产品类解耦合)
优化后
优化工厂类
/*** todo 反射工厂(通过产品全类名来创建产品) (工厂和产品解耦合)*/public static Product createProductReflect(String Full_product_name ) {Product product = null;try {//根据产品类的全类名反射生成产品类的class字节对象Class<?> aClass = Class.forName(Full_product_name);//通过产品类的字节码对象 创建真实对象product = (Product) aClass.newInstance();}catch (Exception e){e.printStackTrace();}return product;}
测试类:
//全类名反射通过工厂生产产品Product A = Product_factory.createProductReflect("factory.Simple_factory.ProductA");A.show();Product B = Product_factory.createProductReflect("factory.Simple_factory.ProductB");B.show();Product C = Product_factory.createProductReflect("factory.Simple_factory.ProductC");B.show();
输出:
A产品被生产了
B产品被生产了
B产品被生产了
这样如果要追加产品D,只需要新增产品D,无需修改工厂,只需要在需要D产品时,通过对工厂引入产品的全类名就可以生产产品类对象
新增产品D
public class ProductD implements Product{@Overridepublic void show() {System.out.println("D产品被生产了");}
}
通过对工厂引入产品的全类名生产产品类对象
Product D = Product_factory.createProductReflect("factory.Simple_factory.ProductD");D.show();
输出:
D产品被生产了
使用Java反射机制优化简单工厂模式后,可以看到,
不论具体产品类更新多频繁,都不需要再修改工厂类
,从而解决了普通简单工厂模式操作成本高和系统复杂性高的问题~
3.1.3 利用反射再优化(配置文件配置全类名映射)
简单工厂模式的工厂类采用Java反射机制进行优化后,此时的仍然存在这样一个问题,
子类的全局定名(包名+类名)是写死的
,但是实际上开发者在写代码时是很难提前预知所有的子类的全局定名(包名+类名)的,因此需要进行二次优化~
优化思路:
通过配置文件方式,
统一定义类名对应全局定名(包名+类名),将配置文件存放到资源目录下
,程序运行时通过ClassLoader类加载器动态获取到配置文件中定义的子类的全局定名
~
再次优化步骤2:配置类名对应全局定名(包名+类名)
创建属性配置文件Product.properties
//产品抽象类Product相关子类的全局定名(包名+类名)定义
//key value
ProductA = com.justin.java.lang.ProductA
ProductB = com.justin.java.lang.ProductB
ProductC = com.justin.java.lang.ProductC
再次优化步骤3:修改调用工厂类
public class FactoryTest {@Testpublic void test() throws IOException {ClassLoader classLoader = this.getClass().getClassLoader();Properties prop = new Properties();prop.load(classLoader.getResourceAsStream("Product.properties"));String className = "";try {className = prop.getProperty("ProductA");Product productA = Factory.getInstance(className);productA.show();} catch (NullPointerException e) {System.out.println("没有A这款产品,无法生产~");}try {className = prop.getProperty("ProductB");Product productA = Factory.getInstance(className);productA.show();} catch (NullPointerException e) {System.out.println("没有B这款产品,无法生产~");}try {className = prop.getProperty("ProductC");Product productA = Factory.getInstance(className);productA.show();} catch (NullPointerException e) {System.out.println("没有C这款产品,无法生产~");}}
}
输出:
生产了产品A
生产了产品B
生产了产品C
相比较优化前,将产品类对应的全类名,放在了配置文件里面,在生产产品时,根据以下配置将产品类对应的全类名从配置文件里面取到,然后再根据全类名反射构建产品对象:
ClassLoader classLoader = this.getClass().getClassLoader();Properties prop = new Properties();prop.load(classLoader.getResourceAsStream("Product.properties"));
classLoader.getResourceAsStream("Product.properties")
是通过类加载器来获取资源文件 “Product.properties” 的输入流。getResourceAsStream() 方法是 java.lang.ClassLoader 类的一个方法,它可以根据给定的路径从类路径中查找并返回对应的资源文件的输入流。
prop.load()
是 java.util.Properties 类的一个方法,用于将输入流中的数据加载到属性对象中。
在这行代码中,prop 是一个属性对象,通过调用 prop.load() 方法,并将类加载器获取到的资源文件输入流作为参数,实现将资源文件的内容加载到属性对象中。
综上所述,这行代码的作用是使用类加载器加载名为 "Product.properties" 的资源文件,并将其读取为属性对象。这样可以方便地获取和操作资源文件中定义的属性值。
3.2 代理模式中的动态代理实现
代理模式是什么?
代理(Proxy)模式是一种设计模式,通过代理对象来访问目标对象,还可以在不修改目标对象的情况下,对代理对象进行拓展,增强目标对象的功能~
3.2.1 静态代理
静态代理是在编译时就已经确定代理类和被代理类的关系
,代理类和被代理类实现同一个接口或继承同一个父类
。代理类持有对被代理对象的引用(代理对象),在调用目标方法之前或之后执行一些额外的逻辑
。静态代理的代码在编译时就已经确定,因此代理类需要为每一个被代理类编写一个对应的代理类。这种方式的好处是简单直观,容易理解和掌握,但是当被代理的类较多时,会产生大量的重复代码。
也就是一个被代理类对应着一个代理类,但是当被代理的类较多时,会产生大量的重复代码。
其实静态代理通俗的来说,就是
被代理类和代理类共同实现一个接口
,并且实现接口的方法,代理类通过声明被代理类的实例化对象(代理对象)
(也就是编译时就已经确定代理类和被代理类的关系),通过调用和被代理类一样的方法
(这就是为什么要共同实现一个接口的方法),并且在代理类方法中通过代理对象调用被代理类的方法
(可以在被代理类的方法做出增代理类设置的增强),从而达到代理或代理增强的效果
3.2.2 动态代理
动态代理是在运行时生成代理类,不需要对每个被代理类都编写一个对应的代理类
。它通过使用 Java 的反射机制,在运行时动态地创建代理类和代理对象
。代理类实现一个统一的接口或继承一个父类
,并持有一个 InvocationHandler 对象作为其调用处理器。在调用目标方法时,代理类会将方法调用转发给 InvocationHandler 处理器,并可以在调用之前或之后添加额外的逻辑
,动态代理的优势在于可以更加灵活地动态创建代理对象,减少了重复的代理类编写,适用于代理类较多或需要动态管理代理对象的场景。
3.2.2.1 JDK动态代理(反射构造代理对象)
JDK 原生动态代理,主要利用了JDK API的
java.lang.reflect.Proxy
和java.lang.relfect.InnvocationHandler
这两个类来实现~
通过java.lang.reflect.Proxy代理类的newProxyInstance方法
,传递3个参数,分别是:
- 目标对象的加载器 通过Object.getClass().getClassLoader方式获取
- 目标对象的实现接口类型 通过Object.getClass().getInterfaces()方式获取
- InnvocationHandler事件处理器 通过new实例化对象并重写invoke方法方式获取
步骤:
- 创建被代理类的接口,让被代理类实现接口方法
- 创建代理类,通过构造方法将被代理类对象注入到代理类
- 通过设置3个参数(1、目标对象的加载器,2、目标对象的实现接口类型,3、InnvocationHandler事件处理器(增强目标对象的方法))
- 编写一个返回代理对象的方法:通过Proxy代理类的newProxyInstance方法将三个参数传入,返回生成的代理对象。
- 在测试类中将被代理类对象通过代理类有参构造引入,然后生成代理对象,执行增强的方法
举例:
产品类接口Product_interface
/*** 被代理类接口*/
public interface Product_interface {void sell();
}
产品类Product
/*** @Description TODO 被代理类**/
public class Product implements Product_interface{@Overridepublic void sell() {System.out.println("生产了一台iphone 15 pro max");}
}
代理类ProductProxy
/*** @Description TODO 动态代理类**/
public class ProductProxy {private Object target;//被代理的对象public ProductProxy (Object target){//通过构造方法引入被代理对象this.target = target;}/*** 利用JDK API获取到代理对象* @return*/public Object getProxyInstance(){//目标对象的加载器ClassLoader classLoader = target.getClass().getClassLoader();//反射//目标对象的实现接口类型Class<?>[] interfaces = target.getClass().getInterfaces();//反射//InvocationHandler事件处理器实例对象InvocationHandler invocationHandler = new InvocationHandler() {@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {//前置增强System.out.println("提前接到消息的黄牛正在蹲抢中.............");// 执行目标对象方法Object value = method.invoke(target, args);//后置增强System.out.println("无货......................");return null;//若无返回值 就直接返回 若需要返回一个返回值 就如实返回}};//传入3个参数,创建代理类的实例对象,并返回return Proxy.newProxyInstance(classLoader,interfaces,invocationHandler);}
}
测试类ProductBuyTest
public static void main(String[] args) {Product_interface product = new Product();//创建被代理类对象ProductProxy productProxy = new ProductProxy(product);//将被代理类的对象交给代理类Product_interface proxy = (Product_interface) productProxy.getProxyInstance();//由代理类生成代理对象proxy.sell();//通过代理对象执行被代理类的增强方法}
输出:
提前接到消息的黄牛正在蹲抢中.............
富士康生产了一台iphone 15 pro max
无货......................
JDK原生动态代理中,获取代理示例对象过程中,获取目标对象的类加载器,通过
target.getClass().getClassLoader获取到目标对象的类加载器
,target.getClass()方式获取目标对象的Class实例对象
使用的就是Java反射机制来实现的~
3.2.2.2 cglib动态代理(没有用反射)
CGLIB(Code Generation Library)是一个基于ASM(一个Java字节码操作框架)的代码生成库
,它可以在运行时动态地生成目标类的子类
,从而实现对目标类的代理
。
使用时需引入cglib依赖
<dependency><groupId>cglib</groupId><artifactId>cglib</artifactId><version>2.2.2</version></dependency>
产品类Product
/*** 被代理类*/
public class Product {public void sell() {System.out.println("富士康生产了一台iphone 15 pro max");}
}
代理类CglibProxy
/*** @Description: 代理类 用来获取代理对象*/
public class CglibProxy implements MethodInterceptor {private Object target;//被代理的对象public CglibProxy (Object target){//通过构造方法引入被代理对象this.target = target;}/*** 用于构造代理对象* @return*/public Object getProxyObject() {//创建Enhancer对象,类似于JDK代理中的Proxy类Enhancer enhancer = new Enhancer();//设置父类的字节码对象。指定父类enhancer.setSuperclass(target.getClass());//设置回调函数enhancer.setCallback(this);//创建代理对象Object proxyObject = enhancer.create();return proxyObject;}/** 拦截器* 1.目标对象的方法调用* 2.行为增强* 参数 o: cglib 动态生成的代理类的实例* method:实体类所调用的都被代理的方法的引用* objects 参数列表* methodProxy:生成的代理类对方法的代理引用* */public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {//前置增强System.out.println("提前接到消息的黄牛正在蹲抢中.............");//要调用目标对象的方法Object obj = method.invoke(target, objects);//后置增强System.out.println("无货......................");return null;}
}
输出:
提前接到消息的黄牛正在蹲抢中.............
富士康生产了一台iphone 15 pro max
无货......................
实现步骤:
- 引入cglib依赖
- 创建被代理类
- 创建cglib代理类并且实现MethodInterceptor 接口,重写intercept方法
- 通过构造方法注入被代理类对象给代理对象赋值
- 编写一个返回代理对象的方法:
1、创建Enhancer对象,
2、给Enhancer对象设置父类(被代理类)的字节码对象,
3、给Enhancer对象设置回调函数,
4、创建代理对象 返回代理对象 - 在intercept方法里面调用目标对象的方法(增强)
- 在测试类中将被代理类对象通过代理类有参构造引入,然后生成代理对象,执行增强的方法
参考来自:
Java–反射机制原理、几种Class获取方式及应用场景—作者:吾日三省贾斯汀
相关文章:

【Java基础】深入理解反射、反射的应用(工厂模式、代理模式)
文章目录 1. Java反射机制是什么?1.2 Java反射例子 2. Java反射机制中获取Class的三种方式及区别?3. Java反射机制的应用场景有哪些?3.1. 优化静态工厂模式(解耦)3.1.1 优化前(工厂类和产品类耦合ÿ…...

VUE 项目 nginx部署
server {listen 80; # 监听的端口号server_name 129.204.189.149; # 服务器的ip或者域名#charset koi8-r;#access_log logs/host.access.log main;# 前端服务反向代理配置location / {proxy_http_version 1.1;proxy_set_header Host $host;proxy_set_header X-Real-…...

Hashtable和HashMap、ConcurrentHashMap 之间的区别
Hashtable和HashMap的区别 HashMap和Hashtable都是哈希表数据结构,但是Hashtable是线程安全的,HashMap是线程不安全的 Hashtable实现线程安全就是简单的把关键方法都加上了synchronized关键字 直接在方法上添加synchronized相当于针对this对象࿰…...

包管理工具--》npm的配置及使用(二)
在阅读本篇文章前请先阅读包管理工具--》npm的配置及使用(一) 目录 🌟语义版本 避免还原的差异 npm的差异版本处理 🌟npm 脚本 (npm scripts) 🌟运行环境配置 在node中读取package.json …...

【Linux】多线程2——线程互斥与同步/多线程应用
文章目录 1. 线程互斥1.1 问题引入1.2 线程互斥的相关概念1.3 互斥量mutex1.4 互斥量实现原理1.5 死锁 2. 线程安全和可重入函数3. 线程同步3.1 同步概念3.2 条件变量 4. 生产消费模型4.1 基于阻塞队列的cp模型4.2 基于环形队列的cp模型POSIX信号量 5. 线程池5.1 互斥量RAII版本…...

Python中的函数式编程是什么?
Python中的函数式编程是一种编程范式,它强调使用纯函数和避免可变状态来构建程序。函数式编程的核心思想是将计算视为函数的求值,而不是通过改变状态来实现。在函数式编程中,函数被视为一等公民,可以作为参数传递给其他函数&#…...

8月《中国数据库行业分析报告》已发布,聚焦数据仓库、首发【全球数据仓库产业图谱】
为了帮助大家及时了解中国数据库行业发展现状、梳理当前数据库市场环境和产品生态等情况,从2022年4月起,墨天轮社区行业分析研究团队出品将持续每月为大家推出最新《中国数据库行业分析报告》,持续传播数据技术知识、努力促进技术创新与行业生…...

TikTok Shop|如何成为定邀卖家?
TikTok在商品售卖资质和商家资质上做了很多限制,比如我们熟知的珠宝类目,今天我们结合TikTok Shop规则中心8月30号发布的《如何申请成为“定邀”卖家》和关于“定邀”商品的政策进行分析,看看如何成为“定邀”卖家。 定邀商品/类目有哪些&am…...

C++二级题目6
数字放大 #include<iostream> #include<string.h> #include<stdio.h> #include<iomanip> #include<cmath> #include<bits/stdc.h> int a[2000][2000]; int b[2000]; char c[2000]; long long n; using namespace std; int main() {int x;…...

南方科技大学博士研究生奖助学金,深圳大学
目录 南方科技大学 中南大学 南京大学 厦门大学 苏州大学 中南财经政法大学 深圳大学 南方科技大学 https://ocean.sustech.edu.cn/ocean/public/upload/download/3/2.pdf 南方科技大学的在读研究生,每人每年都会得到40000元的补助,这40000块钱分…...

QT 使用信号与槽实现界面跳转
一、创建一个新的页面 1 > 在原有工程上新建一个页面 2 > 选择Qt - Qt 设计师界面类 - choose 3 > 选择Widget模板 - 下一步 4 > 输入自定义类名 - 下一步 会自动生成其同名的.h .cpp .ui文件 5 > 最终效果 Headers存放.h文件 Soueces存放.cpp文件 Forms存放.u…...

Burp插件HaE与Authz用法
HaE与Authz均为BurpSuite插件生态的一员,两者搭配可以避免“越权”、“未授权”两类漏洞的重复测试行为。(适用于业务繁杂,系统模块功能多的场景) 两个插件都可以在store里安装 安装完后,点击Filter Settings勾选Sho…...

element+vue table表格全部数据和已选数据联动
1.组件TableChoose <template><div class"tableChooseBox"><div class"tableRow"><div class"tableCard"><div class"tableHeadTip">全部{{ labelTitle }}</div><slot name"body" …...

vue 防抖与节流用法
一、html <template><button click"getData">获取数据</button> </template>二、JS import { throttle } from "/utils/common"; export default {methods:{getData: throttle(async function(params){console.log(”获取接口数…...

IntelliJ IDEA创建Web项目并使用Web服务器----Tomcat
🏆IntelliJ IDEA创建Web项目并使用Web服务器----Tomcat 以下是本篇文章正文内容,下面案例可供参考(提示:本篇文章属于原创,请转发或者引用时注明出处。),大家记得支持一下!ÿ…...

rk3399 linux 5.10 usb 2.0设备上电概率性注册失败
多次开关机,发现usb hub和4G都通信失败了,这就有点奇怪了,按理说usb驱动是没啥问题的 先查看usb log rootlinaro-alip:/# dmesg | grep usb [ 1.723797] usbcore: registered new interface driver usbfs [ 1.723828] usbcore: regis…...

OpenHarmony 4.0 源码编译hb 问题排查记录
OS:Ubuntu 22.04 x86_64 下载好Openharmony 4.0Beta2 的源码 $ pip3 install ohos-build $ cd openharmony-4.0b2 $ hb set Traceback (most recent call last):File "/home/loongson/.local/bin/hb", line 8, in <module>sys.exit(main())File "/home/…...

Ubuntu20 安装 带cuda的opencv遇到的问题
问题1: CUDA 12.2 fp16 dnn 编译错误 错误 C2666: operator !: 具有类似的转换重载函数 解决: CUDA 12.2 fp16 dnn compilation error Issue #23893 opencv/opencv GitHub Solution: I "solved" this by using static_cast. You want …...

【每日运维】U盘启动盘安装 ESXi 6.7.0 安装卡在 loading /bnxtroce.v00
问题描述 ● ESXi 6.7.0 安装进度卡在loading /bnxtroce.v00 进度处 处理方法 ● 重新制作启动盘,写入方式改为:【USB-ZIPv2】 ● 设置服务器的 bios设置,启动方式改为【UEFI】 ● 重启开机安装即可...

Linux的服务器日志分析及性能调优
作为网络安全和数据传输的重要环节,代理服务器在现代互联网中扮演着至关重要的角色。然而,在高负载情况下,代理服务器可能面临性能瓶颈和效率问题。本文将介绍如何利用Linux系统对代理服务器进行日志分析,并提供一些实用技巧来优化…...

java 浅谈ThreadLocal底层源码(通俗易懂)
目录 一、ThreadLocal类基本介绍 1.概述 : 2.作用及特定 : 二、ThreadLocal类源码解读 1.代码准备 : 1.1 图示 1.2 数据对象 1.3 测试类 1.4 运行测试 2.源码分析 : 2.1 set方法解读 2.2 get方法解读 一、ThreadLocal类基本介绍 1.概述 : (1) ThreadLocal,本…...

前端实习day37~day38
昨晚太累了,就没有写博客,今天一起写好了,在昨天和今天的努力下,终于把业务模型的基本版本跑通了,明天再补充一下小接口,然后再把一些异常情况判断一下,争取明天弄完,然后早点下班&a…...

题目:2635.转换数组中的每个元素
题目来源: leetcode题目,网址:2635. 转换数组中的每个元素 - 力扣(LeetCode) 解题思路: 按要求模拟即可。 解题代码: /*** param {number[]} arr* param {Function} fn* return {number[]}…...

Docker Compose具体应用
文章目录 介绍安装和配置编写docker-compose.yml文件docker-compose执行时注意事项常用命令和操作高级特性和扩展总结 介绍 Docker Compose的概述 Docker Compose是一个用于定义和运行多容器Docker应用程序的工具。它使用YAML文件来配置应用程序需要的服务、网络和卷等资源。 …...

FastAPI 参数的作用
FastAPI是一个现代化的Python web框架,其参数具有重要的作用。在FastAPI中,参数被用于接收HTTP请求中的数据及其它相关信息。 FastAPI支持的参数类型包括: 查询参数(query parameters) 查询参数是指将参数附加到URL末…...

国内免费无限制的chatgpt导航和ai画画
非常实用的AI网址导航,其实际使用体验非常便捷。该导航系统不仅提供了全面的网站分类和搜索功能,还对每个网站进行了精准的评估和排序。推荐高质量的网站资源,并实时检测网站的安全性,保障用户的上网安全。 总的来说:…...

【USRP】集成化仪器系列2 :示波器,基于labview实现
USRP 示波器 1、设备IP地址:默认为192.168.10.2,请勿 修改,运行阶段无法修改。 2、中心频率:当需要生成不同频率单载波的 时候请直接修改中心频率,在运行的时候您 也可以直接修改中心频率。 3、接收增益:…...

Linux map type uncache 和 write combine区别
文章目录 前言一、定义二、隐含区别总结 前言 这段时间被Map Cache Type坑了一次。 GPU的PCI bar地址map成uncache 的还是 write combine? 一、定义 uncache(uc) : map后,CPU读写不经过Cache write combine(wb): map后,CPU读写同…...

【业务功能篇93】微服务-springcloud-多线程-异步处理-异步编排-CompletableFutrue-实战运用
异步处理编排 我们可以在商品详细信息查询的位置实现CompletableFuture的异步编排处理。 根据业务分析:3.4.5数据接口的入参信息需要来源于1数据接口的返回信息,也就是skuid 所以可以设计 1 3 4 5 串行线程 ,而 3 4 5依赖1 ,需要等…...

哈希的应用——位图
文章目录 前言1. 面试题思考2. 位图2.1 位图的概念2.2 思路讲解及代码实现结构定义构造函数set和reset接口实现set和reset测试观察test接口实现test接口测试思考 3. 位图的应用习题1习题2习题3 4. 总结5. 源码5.1 bitset.h5.2 Test.c 前言 前面的文章里我们学习了哈希表&#x…...