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

Java反射(三)

目录

1.反射与代理设计模式

2.反射与Annotation

3.自定义Annotation

4.Annotation整合工厂设计模式和代理设计模式


1.反射与代理设计模式

代理模式是指通过业务真实类实现业务接口,再通过设置代理类创建业务真实类子类从而间接访问业务真实类。但是这存在一个弊端,如果有1000个业务接口,对应的业务就需要实例化1000个对象,如下

代理设计模式

package Example1709;
//业务接口实现发送消息
interface Message{public void  send();
}
//业务接口真实实现
class MessageReal implements Message{@Overridepublic void send() {System.out.println("传输信息Message");}
}
//代理类
class Proxy{
//    通过实例化子类进行间接实现功能private MessageReal real = new MessageReal();public void getMessage() {real.send();}
}
public class javaDemo {public static void main(String[] args) {Proxy p = new Proxy();p.getMessage();}
}

 可以看到代理类里面创建了Message实例对象,通过代理设计就可以实现客户端无需创建相应对象就能调用其中方法,只需要创建代理类即可。但是如果业务非常多,而我仅需要其中一个业务功能,那么代理类创建的对象将浪费。所以可以通过反射实现动态代理

java中特地有InvocationHandle接口实现动态代理,只需要让代理类实现该接口并且覆写其中方法invoke()方法调用 就能实现动态代理

案例代码:

package Example1710;import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
//业务接口
@FunctionalInterface
interface Message{public void send();
}
interface Connect{public boolean connect();
}
interface Close{public void close();
}
//业务实现类
class MessageReal implements Message{@Overridepublic void send() {System.out.println("输出信息");}
}
class ConnectReal implements Connect{@Overridepublic boolean connect() {System.out.println("连接成功");return true;}
}
class closeReal implements Close{@Overridepublic void close() {System.out.println("断开连接");}
}
//代理类需要实现InvocationHandle接口
class MessageProxy implements InvocationHandler {private Object object;public Object bind(Object object){this.object = object;return Proxy.newProxyInstance(object.getClass().getClassLoader(), object.getClass().getInterfaces(),this);}
//覆写InvocationHandle接口中的invoke方法实现方法的调用@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("当调用方法时候自动执行这个函数");Object returnData = null;returnData = method.invoke(this.object,args);return returnData;}
}
public class javaDemo {public static void main(String[] args) {
//        向上转型实现需要的代理类Connect con = (Connect) new MessageProxy().bind(new ConnectReal());con.connect();}
}

 


2.反射与Annotation

在java.lang.reflect中通过AccesibleObject类可以获取Annotation(注解)。

AccessibleObject类获取Annotation的方法:

方法名返回类型描述
getAnnotations()Annotation[]返回直接存在于此元素上的所有注解。
getAnnotation(Class<T> annotationClass)<T extends Annotation> T如果此元素上存在指定类型的注解,则返回该注解;否则返回 null
getDeclaredAnnotations()Annotation[]返回直接存在于此元素上的所有已声明注解。
getDeclaredAnnotation(Class<T> annotationClass)<T extends Annotation> T如果此元素上存在指定类型的注解,则返回该注解;否则返回 null
isAnnotationPresent(Class<? extends Annotation> annotationClass)boolean如果此元素上存在指定类型的注解,则返回 true;否则返回 false

案例代码:

package Example1711;import java.io.Serializable;
import java.lang.annotation.Annotation;
import java.lang.reflect.AccessibleObject;@Deprecated
@FunctionalInterface
interface Face{void face();
}@SuppressWarnings("serial")
class Test implements Face, Serializable {@Overridepublic void face() {System.out.println("No face");}
}public class javaDemo {public static void main(String[] args) {Annotation tation[] = Face.class.getAnnotations();for (Annotation temp:tation) {System.out.println(temp);}Annotation taion2[] = Test.class.getAnnotations();for (Annotation temp:taion2) {System.out.println(temp);}}
}

 

 上图中可以发现输出的只有interface接口的注解Annotation 但是类的上面的还有类内部的@Override却没有输出。原因在于Annotation的定义范围有关

下面任意拆出一个注解比如@FunctionInterface,分析源码

@Documented
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface FunctionalInterface{}

可以看到其中还定义的范围是Rentention,这里是RUNTIME意思是运行,

@Retention注解用于指定注解的保留策略,有三个可选值:

  • RetentionPolicy.SOURCE:注解只保留在源代码中,编译时会被忽略。
  • RetentionPolicy.CLASS:注解保留在编译后的字节码文件中,但在运行时无法获取到。
  • RetentionPolicy.RUNTIME:注解保留在编译后的字节码文件中,并且可以在运行时通过反射获取到。

问1:Connect con = (Connect) new MessageProxy().bind(new ConnectReal());其中new MessageProxy是创建代理对象,那return Proxy.newProxyInstance(object.getClass().getClassLoader(),this)也是创建代理对象,这不是重复了操作吗,如果和new MessageProxy作用不一样的话,那么newProxyInstance方法有什么作用

 


3.自定义Annotation

开发者可以根据自己的需要自定义Annotation,其中定义Annotaion时候需要使用@interface进行标记,同时通过@Target定义范围

Annotation操作范围:

元素类型@Target 取值描述
类或接口ElementType.TYPE应用于类、接口或枚举类型。
字段ElementType.FIELD应用于字段(成员变量)。
方法ElementType.METHOD应用于方法。
构造方法ElementType.CONSTRUCTOR应用于构造方法。
方法参数ElementType.PARAMETER应用于方法的参数。
局部变量ElementType.LOCAL_VARIABLE应用于局部变量。
注解ElementType.ANNOTATION_TYPE应用于注解类型。
ElementType.PACKAGE应用于包声明。
泛型类型参数ElementType.TYPE_PARAMETER应用于泛型类型参数。
泛型类型参数的边界ElementType.TYPE_USE应用于泛型类型参数的使用处,例如类型转换、instanceof 表达式等
类型导入声明(Java 9+)ElementType.TYPE_IMPORT_DECLARATION应用于类型导入声明。
模块导入声明(Java 9+)ElementType.MODULE_IMPORT_DECLARATION应用于模块导入声明。
类型使用ElementType.TYPE_USEElementType.TYPE_PARAMETER应用于类型使用或泛型类型参数。

 自定义案例代码:

如果@DefaultInterface对象有必要的数据传入,可以在@interface下设置value值。

package Example1713;import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.Method;@Target({ElementType.METHOD,ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@interface useMessage{public String title();public String value();public String Default()default "默认值,如果调用则返回这个默认";
}class Message {@useMessage(title="Annotation的使用标题",value = "value的值")public void send(String str){System.out.println("输出信息"+str);}
}
public class javaDemo {public static void main(String[] args) throws Exception{String str;
//        调用方法Method mehod = Message.class.getMethod("send", String.class);
//        获取指定的AnnotationuseMessage msg = mehod.getAnnotation(useMessage.class);str = msg.Default();
//        实现方法调用mehod.invoke(Message.class.getDeclaredConstructor().newInstance(),str);str = msg.title();mehod.invoke(Message.class.getDeclaredConstructor().newInstance(),str);str = msg.value();mehod.invoke(Message.class.getDeclaredConstructor().newInstance(),str);}
}

4.Annotation整合工厂设计模式和代理设计模式

使用Annotation进行开发时候最大的特点就是可以将相应的配置信息写入Annotation后,在项目启动的时候就能够通过反射获取到相应的Annotation定义并操作

以下案例实现了通过Annotation整合工厂设计模式和代理设计模式

案例代码:

package Example1714;import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;//业务接口
interface Message{public void send(String msg);
}
//业务实现类
class NetMessageImp implements Message{@Overridepublic void send(String msg) {System.out.println("通过网络进行发送消息"+msg);}
}
class CloudMessageImp implements Message{@Overridepublic void send(String msg) {System.out.println("通过云网络进行发送消息"+msg);}
}
//定义工厂类
class Factory{
//    私有化工厂类无法在外部实例化private Factory(){};
//    通过getInstance获取实例化的对象public static<T> T getInstance(Class<T> clazz){try {return (T) new MessageProxy().bind(clazz.getDeclaredConstructor().newInstance());} catch (Exception e){e.printStackTrace();return null;}}
}
//设置自定义Annotation
@Target({ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@interface RealInstance {public Class<?> claszz();}@RealInstance(claszz = NetMessageImp.class)
class MessageService{private Message msg;public MessageService(){
//        getAnnotation需要对应的classRealInstance cls = MessageService.class.getAnnotation(RealInstance.class);this.msg = (Message) Factory.getInstance(cls.claszz());}public void send(String msg){this.msg.send(msg);}
}
//设置代理类
class MessageProxy implements InvocationHandler{private Object target;
//    绑定并创建指定对象public  Object bind(Object target){this.target = target;return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(),this);}
//    设置连接函数public boolean connect(){System.out.println("连接成功");return true;}
//    设置关闭函数public void close(){System.out.println("断开连接");}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {try {if (this.connect()){return method.invoke(this.target,args);}}catch (Exception e){e.printStackTrace();}finally {this.close();}return null;}
}
public class javaDemo {public static void main(String[] args) {MessageService instance = new MessageService();instance.send("我去,这东西是真的复杂啊,需要好好仔细读完啊");}
}

  1. Message接口是一个业务接口,定义了发送消息的方法。
  2. NetMessageImpCloudMessageImp是两个实现了Message接口的具体业务类,分别通过网络和云网络发送消息。
  3. Factory是一个工厂类,通过使用代理模式创建并返回代理对象的实例。
  4. RealInstance是一个自定义注解,用于标记需要被代理的具体业务类。
  5. MessageService是一个具有注解的类,其中msg字段是通过工厂类创建的代理对象,用于发送消息。
  6. MessageProxy是一个实现了InvocationHandler接口的代理类,负责在发送消息前后进行额外的处理,比如连接和关闭连接。
  7. 在主函数中,创建MessageService实例并调用send方法发送消息。

问1:public static<T> T getInstance(Class<T> clazz)为什么要用<T>,作为泛型方法是如何使用的?

public static <T> T getInstance(Class<T> clazz)中的<T>是泛型声明,它允许我们在方法中使用泛型类型。其中,T是一个类型参数,表示方法的返回类型和传入参数的类型。通过在方法声明中使用泛型,我们可以在调用时指定具体的类型,并在编译时进行类型检查。

问2:在这段整合工厂设计和代理设计时候,工厂类和代理类分别担任了什么样的角色?他们完成了什么职责,为什么要加入MessageService?

  1. 工厂类(Factory)的角色是创建并返回代理对象的实例。它的职责是根据传入的业务接口类型,使用代理模式创建该接口的代理对象。工厂类的目的是为了提供一种通用的方式来创建代理对象。
  2. 代理类(MessageProxy)的角色是实现了InvocationHandler接口的代理类。它的职责是在代理对象的方法调用前后进行额外的处理。在这个例子中,它负责在发送消息前后进行连接和关闭连接的操作。
  3. MessageService是一个业务类,其中的msg字段通过工厂类创建的代理对象,用于发送消息。MessageService通过使用代理对象,可以在发送消息的过程中加入额外的处理逻辑,而无需直接引用具体的业务实现类。

问3:Proxy.newProxyInstance()方法如何使用,该怎么传入参数?

Proxy.newProxyInstance()方法用于创建代理对象。它接受三个参数:

  • ClassLoader loader:类加载器,用于在运行时加载代理类。一般可以使用业务接口的类加载器。
  • Class<?>[] interfaces:代理类要实现的接口数组。代理对象将实现这些接口,并将方法调用委托给InvocationHandlerinvoke()方法。
  • InvocationHandler h:代理对象在方法调用时的处理器,需要实现InvocationHandler接口

问4:方法调用method.invoke()如何传入参数?

问4:method.invoke()方法用于调用代理对象的方法。它接受两个参数:

  • Object obj:方法所属的对象,即代理对象。
  • Object... args:方法的参数数组。

问5:在设计模式中,工厂设计模式,代理设计模式,业务处理类的作用?

  1. 在设计模式中,工厂模式的作用是将对象的创建过程封装起来,并且提供一个统一的接口来获取对象的实例。通过使用工厂类,可以实现对象的创建和管理的解耦,使得代码更加灵活和可维护。
  2. 代理模式的作用: 代理模式充当了客户端和实际业务对象之间的中介角色,为客户端提供一种间接访问对象的方式。具体来说,代理类封装了实际业务对象并提供了一个类似的接口,使得客户端可以通过代理类来访问实际业务对象。代理类还可以在访问被代理对象之前或之后执行额外的逻辑(例如验证、缓存、日志记录等)。代理模式的优点是它可以在不修改客户端的情况下对实际业务对象进行控制和扩展。
  3. 业务处理类的作用: 业务处理类是实际执行业务逻辑的类。它是根据特定需求实现业务功能的地方。在代理模式中,业务处理类是被代理的真实对象。它定义了代理类需要代理的具体业务逻辑,代理类会将请求传递给业务处理类并最终由业务处理类完成实际的业务操作。

相关文章:

Java反射(三)

目录 1.反射与代理设计模式 2.反射与Annotation 3.自定义Annotation 4.Annotation整合工厂设计模式和代理设计模式 1.反射与代理设计模式 代理模式是指通过业务真实类实现业务接口&#xff0c;再通过设置代理类创建业务真实类子类从而间接访问业务真实类。但是这存在一个弊…...

ansible-playbook roles编写lnmp剧本

目录 集中式编写lnmp剧本 执行 分布式编写lnmp剧本 一定要设置ssh免交互 nginx mysql php 执行 集中式编写lnmp剧本 vim /etc/ansible/lnmp.yml - name: lnmp playhosts: dbserversremote_user: roottasks:- name: perpare condifurecopy: src/etc/yum.repos.d/nginx.r…...

相机可用性变化监听AvailabilityCallback流程分析

相机可用性变化监听及流程分析 一、接口说明 ​ 相机可用性变化监听可以通过CameraManager中的接口registerAvailabilityCallback()来设置回调&#xff0c;接口如下&#xff1a; /** *注册一个回调以获得有关相机设备可用性的通知。 * *<p>再次注册相同的回调将用提供…...

使用Python多线程实现生产者消费者模型

“Talk is cheap, show me the code.” 废话不多说&#xff0c;直接上代码&#xff1a; """ 生产者消费者模型 Python实现 """ import queue import threading import random import timeclass ConsProd:# 队列参数_que None # 队列# 生产者…...

Notepad++工具通过正则表达式批量替换内容

1.每行末尾新增特定字符串 CtrlH弹出小窗口&#xff1b;查找目标输入$&#xff0c;替换为输入特定字符串&#xff1b;选中循环查找&#xff0c;查找模式选正则表达式&#xff1b;最后点击全部替换 2.每行行首新增特定字符串 CtrlH弹出小窗口&#xff1b;查找目标输入^&…...

从零构建深度学习推理框架-3 手写算子relu

Relu介绍&#xff1a; relu是一个非线性激活函数&#xff0c;可以避免梯度消失&#xff0c;过拟合等情况。我们一般将thresh设为0。 operator类&#xff1a; #ifndef KUIPER_COURSE_INCLUDE_OPS_OP_HPP_ #define KUIPER_COURSE_INCLUDE_OPS_OP_HPP_ namespace kuiper_infer {…...

想做上位机,学C#还是QT?

学习C#还是Qt&#xff0c;取决于你的具体需求和偏好。 如果你计划开发跨平台的桌面应用程序&#xff0c;并且希望使用一种更轻量级、直观的界面框架&#xff0c;那么Qt可能是一个不错的选择。Qt是一个功能丰富且成熟的跨平台框架&#xff0c;支持多种开发语言&#xff08;包括…...

Ansible —— playbook 剧本

Ansible —— playbook 剧本 一、playbook的概述1.playbook简介2.什么是Ansible playbook剧本&#xff1f;3.Ansible playbook剧本的特点4.如何使用Ansible playbook剧本&#xff1f;5.playbooks 本身由以下各部分组成 二、playbook示例1.运行playbook2.定义、引用变量3.指定远…...

ARM寻址方式

寻址方式 寻址方式是根据指令中给出的地址码字段来实现寻找操作数地址的方式&#xff0c;ARM中有以下8种基本的寻址方式。 1、寄存器寻址 将寄存器中的值作为操作数&#xff0c;指令中的地址码字段是寄存器编号。 MOV R1,R2 ;R1 R2 ADD R0,R1,R2 ;R0 R1 R22、立即寻…...

【JAVA】String ,StringBuffer 和 StringBuilder 三者有何联系?

个人主页&#xff1a;【&#x1f60a;个人主页】 系列专栏&#xff1a;【❤️初识JAVA】 文章目录 前言StringBufferStringBuffer方法 StringBuilderStringBuilder方法 String &#xff0c;StringBuffer 和 StringBuilder的区别String和StringBuffer互相转换 前言 在之前的文章…...

关于计数以及Index返回订单号升级版(控制字符长度,控制年月标记)

数据库表操作&#xff1a; EXEC sys.sp_dropextendedproperty nameNName , level0typeNSCHEMA,level0nameNdbo, level1typeNTABLE,level1nameNSetNoIndexGOEXEC sys.sp_dropextendedproperty nameNMS_Description , level0typeNSCHEMA,level0nameNdbo, level1typeNTABLE,level…...

【计算机网络】11、网桥(bridge)、集线器(hub)、交换机(switch)、路由器(router)、网关(gateway)

文章目录 一、网桥&#xff08;bridge)二、集线器&#xff08;hub&#xff09;三、交换机&#xff08;switch)四、路由器&#xff08;router&#xff09;五、网关&#xff08;gateway&#xff09; 对于hub&#xff0c;一个包过来后&#xff0c;直接将包转发到其他口。 对于桥&…...

第九篇-自我任务数据准备

格式化自我意识数据用于ChatGLM微调 准备数据源 https://github.com/hiyouga/ChatGLM-Efficient-Tuning cd data self_cognition.json代码self_process.py #!/usr/bin/python # -*- coding: UTF-8 -*- # 读取self_cognition自我认知解析并写入转换新文件import json# 读取se…...

2023.8.1号论文阅读

文章目录 MCPA: Multi-scale Cross Perceptron Attention Network for 2D Medical Image Segmentation摘要本文方法实验结果 SwinMM: Masked Multi-view with SwinTransformers for 3D Medical Image Segmentation摘要本文方法实验结果 MCPA: Multi-scale Cross Perceptron Att…...

webpack优化前端框架性能

webpack优化目的 webpack优化目的1. 提升开发体验提升开发体验使用 SourceMap 2. 提升打包构建速度提升打包构建速度&#xff08;开发模式&#xff09;提升打包速度 oneOf提升打包速度 include&#xff08;包含&#xff09;/exclude&#xff08;排除&#xff09;提升第二次打包…...

Unity UGUI的Outline(描边)组件的介绍及使用

Unity UGUI的Outline(描边)组件的介绍及使用 1. 什么是Outline(描边)组件&#xff1f; Outline(描边)组件是Unity UGUI中的一种特效组件&#xff0c;用于给UI元素添加描边效果。通过设置描边的颜色、宽度和模糊程度&#xff0c;可以使UI元素在视觉上更加突出。 2. Outline(描…...

爆改vue3 setup naiveui可编辑table

使用naiveui官网的可编辑table总是报错&#xff0c;所以手写了一个 思路&#xff1a;table数据数组unitMsgArr对应一个布尔的数组isEditArr &#xff0c;点击table可编辑的行数据的时候&#xff0c;更改对应的isEdit为true&#xff0c;此时渲染组件EditCom&#xff0c;在EditC…...

功率放大器的种类有哪三种类型

功率放大器是一种能将输入信号转换为更高功率输出的电子设备。在电子工程和音频领域中&#xff0c;功率放大器通常被分为三种类型&#xff1a;A类、B类和AB类。下面安泰电子将详细介绍这三种类型的功率放大器及其特点。 A类功率放大器 A类功率放大器是一种基本的线性功率放大器…...

HDFS 分布式存储 spark storm HBase

HDFS 分布式存储 spark storm HBase 分布式结构 master slave name node client 负责文件的拆分 128MB 3份 data node MapReduce 分布式计算 离线计算 2.X之前 速度比较慢 对比spark 编程思想 Map 分 Reduce 合 hadoop streaming Mrjob Yarn 资源管理 cpu 内存 MapReduc…...

Vue3文字实现左右和上下滚动

可自定义设置以下属性&#xff1a; 滚动文字数组&#xff08;sliderText&#xff09;&#xff0c;类型&#xff1a;Array<{title: string, link?: string}>&#xff0c;必传&#xff0c;默认[] 滚动区域宽度&#xff08;width&#xff09;&#xff0c;类型&#xff1a…...

深入浅出Asp.Net Core MVC应用开发系列-AspNetCore中的日志记录

ASP.NET Core 是一个跨平台的开源框架&#xff0c;用于在 Windows、macOS 或 Linux 上生成基于云的新式 Web 应用。 ASP.NET Core 中的日志记录 .NET 通过 ILogger API 支持高性能结构化日志记录&#xff0c;以帮助监视应用程序行为和诊断问题。 可以通过配置不同的记录提供程…...

C++初阶-list的底层

目录 1.std::list实现的所有代码 2.list的简单介绍 2.1实现list的类 2.2_list_iterator的实现 2.2.1_list_iterator实现的原因和好处 2.2.2_list_iterator实现 2.3_list_node的实现 2.3.1. 避免递归的模板依赖 2.3.2. 内存布局一致性 2.3.3. 类型安全的替代方案 2.3.…...

docker详细操作--未完待续

docker介绍 docker官网: Docker&#xff1a;加速容器应用程序开发 harbor官网&#xff1a;Harbor - Harbor 中文 使用docker加速器: Docker镜像极速下载服务 - 毫秒镜像 是什么 Docker 是一种开源的容器化平台&#xff0c;用于将应用程序及其依赖项&#xff08;如库、运行时环…...

python/java环境配置

环境变量放一起 python&#xff1a; 1.首先下载Python Python下载地址&#xff1a;Download Python | Python.org downloads ---windows -- 64 2.安装Python 下面两个&#xff0c;然后自定义&#xff0c;全选 可以把前4个选上 3.环境配置 1&#xff09;搜高级系统设置 2…...

ssc377d修改flash分区大小

1、flash的分区默认分配16M、 / # df -h Filesystem Size Used Available Use% Mounted on /dev/root 1.9M 1.9M 0 100% / /dev/mtdblock4 3.0M...

第一篇:Agent2Agent (A2A) 协议——协作式人工智能的黎明

AI 领域的快速发展正在催生一个新时代&#xff0c;智能代理&#xff08;agents&#xff09;不再是孤立的个体&#xff0c;而是能够像一个数字团队一样协作。然而&#xff0c;当前 AI 生态系统的碎片化阻碍了这一愿景的实现&#xff0c;导致了“AI 巴别塔问题”——不同代理之间…...

什么是EULA和DPA

文章目录 EULA&#xff08;End User License Agreement&#xff09;DPA&#xff08;Data Protection Agreement&#xff09;一、定义与背景二、核心内容三、法律效力与责任四、实际应用与意义 EULA&#xff08;End User License Agreement&#xff09; 定义&#xff1a; EULA即…...

项目部署到Linux上时遇到的错误(Redis,MySQL,无法正确连接,地址占用问题)

Redis无法正确连接 在运行jar包时出现了这样的错误 查询得知问题核心在于Redis连接失败&#xff0c;具体原因是客户端发送了密码认证请求&#xff0c;但Redis服务器未设置密码 1.为Redis设置密码&#xff08;匹配客户端配置&#xff09; 步骤&#xff1a; 1&#xff09;.修…...

基于 TAPD 进行项目管理

起因 自己写了个小工具&#xff0c;仓库用的Github。之前在用markdown进行需求管理&#xff0c;现在随着功能的增加&#xff0c;感觉有点难以管理了&#xff0c;所以用TAPD这个工具进行需求、Bug管理。 操作流程 注册 TAPD&#xff0c;需要提供一个企业名新建一个项目&#…...

AGain DB和倍数增益的关系

我在设置一款索尼CMOS芯片时&#xff0c;Again增益0db变化为6DB&#xff0c;画面的变化只有2倍DN的增益&#xff0c;比如10变为20。 这与dB和线性增益的关系以及传感器处理流程有关。以下是具体原因分析&#xff1a; 1. dB与线性增益的换算关系 6dB对应的理论线性增益应为&…...