不要再稀里糊涂的使用反射了,四万字带你搞定Java反射(JDK8)

news2024/11/19 3:35:40

文章目录

  • 前言
  • Java反射体系概述
  • 类型信息(Type)
    • GenericDeclaration
    • AnnotatedType
  • 成员信息(Member)
    • 属性信息(Field)
    • 构造函数信息(Constructor)
    • 方法信息(Method)
  • 修饰符信息(Modifier)
  • 参数信息(Parameter)
  • 注解信息(AnnotatedElement)
  • Class

前言

阅读本文要求对Java和JVM具有一定程度的了解,请先看下面几个基础问题:

  • 一个类的加载过程是怎样的?
  • 泛型的实现原理是什么?
  • 协变返回类型是什么?
  • 桥接方法是什么?
  • 实例方法和内部类构造函数第一个隐藏参数分别是什么?

如果不能回答出以上问题,建议再复习一下Java语法。通过本文你将彻底掌握反射。

Java反射体系概述

类加载器通过一个类的全限定类名加载此类的字节码文件,并将字节码文件的静态存储结构转化为元空间的运行时数据结构,接着在堆中生成一个代表这个类的java.lang.Class对象作为元空间这个类的各种元数据的接口,我们可以在程序中获取类的Class对象,从而获得在运行时分析类的能力,这就是反射。

在这里插入图片描述

Class代表Java中的类、接口、枚举、注解(以上这些不含类型变量的类型被称为原始类型)、数组和基本类型。这在没有泛型之前完全够用,但在泛型加入后,由于其擦除方式的实现,导致泛型信息不被保存到字节码文件中,此时Class就不太够用了,因此我们会发现一个有趣的事情,Class是JDK1的API,但却实现了来自JDK5的三个接口。其中TypeGenericDeclaration接口就用于协助Clss获取泛型信息。

Type
Class
GenericDeclaration
AnnotatedElement

JDK5后又加入了一个全新的原始类型——注解。注解十分的特殊,它既是一种类型,又可以作为一种标记并几乎可以添加到Java类的任何位置。AnnotatedElement接口就代表Java中所有可以被注解的元素。

类型信息(Type)

Type
Class
ParameterizedType
GenericArrayType
TypeVariable
WildcardType
//Type中的方法
String	getTypeName()//获取类型的描述字符串

Type是Java中所有类型的超级接口。这些类型包括:

  • 原始类型:即不含类型参数的类、接口、枚举和注解。
  • 基本类型:即八种基本类型。
  • 参数化类型:即含有类型参数的类和接口。
  • 数组类型:即数组。
  • 类型变量:即泛型定义时的类型变量。
  • 通配符类型:即通配符类型。

Class只能获取原始类型和基本类型的完整类型信息,如果使用Class获取其它类型的类型信息那么只能获取其擦除后类型(也就是擦除后对应的原始类型)的类型信息。为此Type框架提供四个子接口用于封装被泛化的类型,并在其中提供方法用于获取那些Class获取不到类型信息。这四个子接口分别是:

  • ParameterizedType:参数化类型的封装接口。
Type[] getActualTypeArguments()//获取参数化类型的类型参数的类型
Type getRawType()//获取参数化类型对应的原始类型
Type getOwnerType()//获取参数化类型的所属类型,没有返回null
  • GenericArrayType:数组类型中泛型数组的封装接口。
Type getGenericComponentType()//获取数组的成员类型
  • TypeVariable<D extends GenericDeclaration>:类型变量的封装接口。
D getGenericDeclaration()//获取声明该类型变量的类型
Type[] getBounds()//获取类型变量的约束列表的类型
String getName()//获取类型变量名
  • WildcardType:通配符类型的封装接口。
Type[] getLowerBounds()//获取通配符下界的类型
Type[] getUpperBounds()//返回通配符上界的类型

GenericDeclaration

GenericDeclaration
Class
Executable
Constructor
Method

GenericDeclaration是所有可以声明泛型的元素,在Java中能声明泛型的元素只有类、方法和构造函数。

TypeVariable<?>[] getTypeParameters()//获取泛型变量

AnnotatedType

AnnotatedType
AnnotatedParameterizedType
AnnotatedArrayType
AnnotatedTypeVariable
AnnotatedWildcardType
//AnnotatedType中的方法
Type getType()//返回该元素的类型

AnnotatedType是Java中所有可以被注解类型的超级接口,通过AnnotatedType可以利用注解作为标记并几乎可以添加到Java类任何位置的特性,间接获取类型信息。AnnotatedType也有四个子接口用于对泛化类型进行封装,它们分别是:

  • AnnotatedParameterizedType:带注解的参数化类型的封装接口。
AnnotatedType[]	getAnnotatedActualTypeArguments()//获取参数化类型的类型参数的AnnotatedType
  • AnnotatedArrayType:带注解的泛型数组的封装接口。
AnnotatedType getAnnotatedGenericComponentType()//获取数组的成员的AnnotatedType

AnnotatedTypeVariable:带注解的类型变量的封装接口。

AnnotatedType[]	getAnnotatedBounds()//获取类型约束列表的AnnotatedType
  • AnnotatedWildcardType:带注解的通配符类型的封装。
AnnotatedType[]	getAnnotatedLowerBounds()//获取通配符下界的AnnotatedType
AnnotatedType[]	getAnnotatedUpperBounds()//返回通配符上界的AnnotatedType

AnnotatedType框架与Type框架在结构上极其相似,但具有两种根本性的差异:

  • AnnotatedType既是一个超级接口又代表着可注解的原始类型和基本类型;Type仅是一个超级接口,它的实现类Class代表原始类型和基本类型。
  • AnnotatedType框架具有潜在性。以一个List<Integer>字段为例,当我们获取它的AnnotatedType时,即使它没有被注解,也会返回一个AnnotatedParameterizedType实例。

两者之间的对应关系如下:

在这里插入图片描述

成员信息(Member)

Member
Executable
Field
Constructor
Method

Member是所有成员的超级接口,一个类的成员只有三种:字段(Field)、构造函数(Constructor)和方法(Method)。Member提供的方法如下:

Class<?> getDeclaringClass()//获取声明该成员的类或接口
int	getModifiers()//获取该成员的修饰符
String getName()//获取该成员的名称
boolean	isSynthetic()//判断该成员是否由编译器自动生成

其中构造函数(Constructor)和方法(Method)都是可执行的,并实现了Executable接口,Executable提供的方法如下:

//获取声明异常的Class数组
Class<?>[] getExceptionTypes()
//获取声明异常的Type数组
Type[] getGenericExceptionTypes()
//获取声明异常的AnnotatedType数组
AnnotatedType[]	getAnnotatedExceptionTypes()

//获取参数的Class数组
Class<?>[] getParameterTypes()
//获取参数的Type数组
Type[] getGenericParameterTypes()
//获取参数的AnnotatedType数组
AnnotatedType[]	getAnnotatedParameterTypes()
//获取参数的数量
int	getParameterCount()
//获取参数的Parameter数组
Parameter[]	getParameters()
//获取参数的注解数组
Annotation[][] getParameterAnnotations()
//获取返回值的AnnotatedType 
AnnotatedType getAnnotatedReturnType()

//获取接收器参数
//所谓接收器参数就是默认传入的参数,实例方法的接收器参数就是this
AnnotatedType getAnnotatedReceiverType()

//获取泛型变量数组
TypeVariable<?>[] getTypeParameters()

//是否有可变参数
boolean	isVarArgs()

//返回一个含有任何类型信息的该可执行元素的描述字符串
String toGenericString()

每个类的成员都有自己权限修饰符,当我们使用FieldConstructorMethod来获取字段值或执行方法时也会被它们自身的权限修饰符所约束,为了让反射更加的强大,JVM提供了AccessibleObject接口,通过该接口就可以抑制成员的访问权限。

AccessibleObject
Executable
Field
Constructor
Method

AccessibleObject接口提供的方法如下:

//判断该成员是否可以访问
boolean	isAccessible()

//设置该成员是否可以访问
void setAccessible(boolean flag)
//静态方法,批量设置成员是否可以访问
static void	setAccessible(AccessibleObject[] array, boolean flag)

属性信息(Field)

Field提供关于类或接口的单个字段的信息和动态访问。这些字段可以是静态字段或实例字段。Field允许在getset访问操作期间发生拓宽转换,但如果发生窄化转换,则抛出异常。Field提供的方法如下:

Class<?> getType()
Type getGenericType()
AnnotatedType getAnnotatedType()

Object get(Object obj)
void set(Object obj, Object value)
boolean	getBoolean(Object obj)
void setBoolean(Object obj, boolean z)
byte getByte(Object obj)
void setByte(Object obj, byte b)
char getChar(Object obj)
void setChar(Object obj, char c)
double getDouble(Object obj)
void setDouble(Object obj, double d)
float getFloat(Object obj)
void setFloat(Object obj, float f)
int	getInt(Object obj)
void setInt(Object obj, int i)
long getLong(Object obj)
void setLong(Object obj, long l)
short getShort(Object obj)
void setShort(Object obj, short s)

//判断该字段是否是枚举类型元素
boolean	isEnumConstant()

//返回一个含有任何类型信息的该可执行元素的描述字符串
String toGenericString()

构造函数信息(Constructor)

Constructor提供关于类的单个构造函数的信息和访问。Constructor允许在实例化时将实际形参进行拓宽转换,但如果发生窄化转换,则抛出异常。Constructor提供的方法如下:

TypeVariable<Constructor<T>>[] getTypeParameters()

//使用此constructor对象表示的构造函数,用指定的初始化参数创建和初始化构造函数的声明类的新实例。
//如果构造函数的声明类是非静态上下文中的内部类,构造函数的第一个参数需要是封闭实例.
//如果所需的访问和参数检查成功,实例化将继续,如果构造函数的声明类尚未初始化,则初始化它。
//如果构造函数正常完成,则返回新创建并初始化的实例。
T newInstance(Object... initargs)

方法信息(Method)

Method提供关于类或接口上单个方法的信息和访问。该方法可以是类方法或实例方法。Method允许在调用方法时将实际形参进行拓宽转换,但如果发生窄化转换,则抛出异常。Method提供的方法如下:

//如果该方法的是注解的成员,则返回该成员的默认值
Object getDefaultValue()

//在具有指定参数的指定对象上调用此method对象表示的底层方法。
//如果方法是静态的,那么指定的obj参数将被忽略。也可以是null。
//如果方法所需的形式形参的数量为0,则提供的args数组的长度可以为0或null。
//如果方法是实例方法,则使用动态方法查找调用它,
//如果基础方法是静态的,如果尚未初始化该方法,则初始化声明该方法的类。
//如果方法正常完成,它返回的值返回给调用者。如果值具有基元类型,则将它转换为包装类型;如果值的类型为基元类型的数组,则返回一个原始类型的数组;如果基础方法返回类型为void,则调用返回null。
Object invoke(Object obj, Object... args)

//判断该方法是否是桥接方法
boolean	isBridge()

//判断该方法是否是默认方法
boolean	isDefault()

修饰符信息(Modifier)

Modifier类提供静态方法和常量来解码修饰符。

//修饰符集使用整数表示
static int ABSTRACT
static int FINAL
static int INTERFACE
static int NATIVE
static int PRIVATE
static int PROTECTED
static int PUBLIC
static int STATIC
static int STRICT
static int SYNCHRONIZED
static int TRANSIENT
static int VOLATILE

//返回一个整数表示可以修饰类的修饰符
static int classModifiers()
//返回一个整数表示可以修饰构造函数的修饰符
static int constructorModifiers()
//返回一个修饰符表示可以修饰字段的修饰符
static int fieldModifiers()
//返回一个修饰符表示可以修饰接口的修饰符
static int interfaceModifiers()
//返回一个修饰符表示可以修饰方法的修饰符
static int methodModifiers()
//返回一个修饰符表示可以修饰参数的修饰符
static int parameterModifiers()

static boolean isAbstract(int mod)
static boolean isFinal(int mod)
static boolean isInterface(int mod)
static boolean isNative(int mod)
static boolean isPrivate(int mod)
static boolean isProtected(int mod)
static boolean isPublic(int mod)
static boolean isStatic(int mod)
static boolean isStrict(int mod)
static boolean isSynchronized(int mod)
static boolean isTransient(int mod)
static boolean isVolatile(int mod)

//返回一个字符串,描述指定修饰符中的访问修饰符标志。
static String toString(int mod)

参数信息(Parameter)

Parameter提供关于方法参数的信息,包括其名称和修饰符。它还提供了获取参数属性的替代方法。

Executable getDeclaringExecutable()
int	getModifiers()
String getName()
Type getParameterizedType()
Class<?> getType()
boolean	isImplicit()
boolean	isNamePresent()
boolean	isSynthetic()
boolean	isVarArgs()

注解信息(AnnotatedElement)

AnnotatedElement
Class
Parameter
AccessibleObject
AnnotatedType
TypeVariable
GenericDeclaration

AnnotatedElement接口将注解分成不同的类型,如果有一个可重复的注解元素Parent,它包含的注解元素为Child,现有一个被注解元素E,则Parent的类型根据情况可分为:

  • 直接存在的注解:Parent直接出现在E上
  • 间接存在的注解:Child直接出现在E上
  • 存在的注解:Parent直接出现在E上或Parent是可继承的并出现在E的父类上
  • 关联的注解:Parent直接出现在E上或Child直接出现在E上或Parent是可继承的并出现在E的父类上
<T extends Annotation> T getAnnotation(Class<T> annotationClass)
Annotation[] getAnnotations()
default <T extends Annotation> T[]	getAnnotationsByType(Class<T> annotationClass)
default <T extends Annotation> T getDeclaredAnnotation(Class<T> annotationClass)
Annotation[] getDeclaredAnnotations()
default <T extends Annotation> T[] getDeclaredAnnotationsByType(Class<T> annotationClass)
default boolean	isAnnotationPresent(Class<? extends Annotation> annotationClass)

不同的方法用于获取不同类型的注解,它们的对应关系如下:

方法名称直接存在的注解间接存在的注解存在的注解关联的注解
getAnnotation
getAnnotations
getAnnotationsByType
getDeclaredAnnotation
getDeclaredAnnotations
getDeclaredAnnotationsByType

Class

  • 方式一:原始类型、数组类型和基本类型可直接使用类名.class的形式:

  • 方式二:Class提供的静态方法forName

//使用指定类加载器加载指定全限定名的类或接口,并只有在initialize为true时才进行初始化
static Class<?> forName(String name,boolean initialize,ClassLoader loader)
//等价于Class.forName(className, true, currentLoader)
static Class<?> forName(String className)
  • 方式三:Object提供的方法getClass
final native Class<?> getClass()
  • 方式四:ClassLoader提供的loadClass方法
//此方式加载的类不会被初始化
Class<?> loadClass(String name) 

Class提供的方法如下:

<U> Class<? extends U> asSubclass(Class<U> clazz)
//将对象强制转换为由此Class对象表示的类或接口
T cast(Object obj)
boolean	desiredAssertionStatus()
//获取加载此类型的类加载器
ClassLoader	getClassLoader()
T newInstance()

//获取该类父接口的Class数组
Class<?>[] getInterfaces()
//获取该类父接口的Type数组
Type[] getGenericInterfaces()
//获取该类父接口的AnnotatedType数组
AnnotatedType[]	getAnnotatedInterfaces()

//获取该类父类的Class对象
Class<? super T> getSuperclass()
//获取该类父类的Type对象
Type getGenericSuperclass()
//获取该类父类的AnnotatedType对象
AnnotatedType getAnnotatedSuperclass()

//查找指定名称的资源
InputStream getResourceAsStream(String name)
URL getResource(String name)

//获取该类型的名称
String getName()
//获取该类的简单名称
String getSimpleName()
//返回由Java语言规范定义的基础类的规范名称。
String getCanonicalName()

//获取该类声明的泛型变量
TypeVariable<Class<T>>[] getTypeParameters()
//获取该类的签名者
Object[] getSigners()
//返回该类的ProtectionDomain。
ProtectionDomain getProtectionDomain()

//返回表示数组的组件类型的Class
Class<?> getComponentType()
//返回此enum类的元素,如果此class对象不表示enum类型,则返回null。
T[]	getEnumConstants()

//获取该类或接口的修饰符
int getModifiers()
//获取该类的包
Package	getPackage()
//获取声明该类或接口类的Class
Class<?> getDeclaringClass()

//如果当前类是匿名内部类,返回它的外围类
Class<?> getEnclosingClass()
//如果当前类是构造函数中的匿名内部类,返回它的外围构造函数
Constructor<?> getEnclosingConstructor()
//如果当前类是方法中的匿名内部类,返回它的外围方法
Method getEnclosingMethod()

//获取一个指定公共字段
Field getField(String name)
//获取一个指定的公共构造函数
Constructor<T> getConstructor(Class<?>... parameterTypes)
//获取一个指定公共方法
Method getMethod(String name,Class<?>... parameterTypes)
//获取所有公共字段
Field[] getFields()
//获取所有公共构造函数
Constructor<?>[] getConstructors()
//获取所有公共方法
Method[] getMethods()
//获取由此类公共的内部类和接口
Class<?>[] getClasses()
//获取一个指定字段
Field getDeclaredField(String name)
//获取一个指定构造函数
Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)
//获取一个指定方法
Method getDeclaredMethod(String name,Class<?>... parameterTypes)
//获取所有字段
Field[] getDeclaredFields()
//获取所有构造函数
Constructor<?>[] getDeclaredConstructors()
//获取所有方法
Method[] getDeclaredMethods()
//获取由此类所有内部类和接口
Class<?>[] getDeclaredClasses()

//判断该类是否是注解类型
boolean	isAnnotation()
//判断该类是否是匿名类
boolean	isAnonymousClass()
//判断该类是否是数组
boolean	isArray()
//是否是枚举
boolean	isEnum()
//判断指定对象是否是与此类兼容
boolean	isInstance(Object obj)
//判断该类是否是与指定类型相同或是指定类型的超类型
boolean	isAssignableFrom(Class<?> cls)
//是否是接口
boolean	isInterface()
//是否是本地类
boolean	isLocalClass()
//是否是内部类
boolean	isMemberClass()
//是否是原始类型
boolean	isPrimitive()
//是否是自动生成的类
boolean	isSynthetic()

//获取含有任何类型信息的该类的描述符
String toGenericString()

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/62913.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

毕业设计-基于机器视觉的指针式仪表智能识别

目录 前言 课题背景和意义 实现技术思路 实现效果图样例 前言 &#x1f4c5;大四是整个大学期间最忙碌的时光,一边要忙着备考或实习为毕业后面临的就业升学做准备,一边要为毕业设计耗费大量精力。近几年各个学校要求的毕设项目越来越难,有不少课题是研究生级别难度的,对本科…

C++ 复制构造函数

在讲解 C 的复制构造函数之前这里先明确一个概念&#xff0c;C 的复制构造函数的意思并不是字面上的意思复制一个构造函数&#xff0c;而是有一种专门用于复制内容的构造函数被叫做复制构造函数。 复制构造函数对于 C 来说是非常重要的概念&#xff0c;所以我们必须掌握并牢记…

jsp设备信息查询系统Myeclipse开发mysql数据库web结构java编程计算机网页项目

一、源码特点 jsp设备信息查询系统 是一套完善的web设计系统&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。开发环境为 TOMCAT7.0,Myeclipse8.5开发&#xff0c;数据库为Mysql&#xff0c;使用…

【算法笔记(六)】检索算法

算法笔记(六) 检索算法算法笔记(六)前言一、线性查找1.什么是线性查找2.需求规则3.人工图示演示4.代码实现二、二分查找1.什么是二分查找2.需求规则3.人工图示演示4.代码实现三.插值查找1.什么是插值查找2.需求规则3.人工图示演示4.代码实现四.斐波那契查找1.什么是斐波那契查找…

[附源码]计算机毕业设计基于springboot框架的资产管理系统设计与实现

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

TCP三次握手四次挥手及常见问题解决方案

一、重要概念 位码即tcp标志位,有6种表示: SYN(synchronous建立连接) ACK(acknowledgement 表示响应、确认) PSH(push表示有DATA数据传输) FIN(finish关闭连接) RST(reset表示连接重置) URG(urgent紧急指针字段值有效) 二、三次握手四次挥手流程图 三、三次握手 第一次握手&am…

一段有关MPU配置代码的几个小疑问

当我们阅读一些STM32F7或STM32H7系列芯片例程&#xff0c;或者基于这两类芯片通过cubeMx进行配置并用到MPU功能时&#xff0c;往往会在代码里看到下面这段MPU配置。对这段代码可能有人有些疑问&#xff0c;这里重点一起聊聊其中的3个&#xff0c;供参考。第一个疑问&#xff0c…

【AI工程论文解读】04-通过Ease.ML/CI实现机器学习模型的持续集成(上)

作者&#xff1a;王磊 更多精彩分享&#xff0c;欢迎访问和关注&#xff1a;https://www.zhihu.com/people/wldandan 持续集成是一种软件开发实践&#xff0c;即团队开发成员经常集成他们的工作&#xff0c;通常每个成员每天至少集成一次&#xff0c;也就意味着每天可能会发生多…

机器人xacro设计+gazebo/rviz启动

机器人xacro设计gazebo/rviz启动项目需求方案机器人的本体设计机器人本体集成car_gazebo.xacroinertial惯性矩阵 head.xacro小车底盘base.xacro摄像头camera.xacro雷达laser.xacro机器joint关节控制器传感器sensor设计机器人joint关节控制器move.xacro摄像头传感器camera_senso…

Metabase学习教程:系统管理-7

使用MetabaseAPI MetabaseAPI简介。 本文介绍如何使用Metabase的API。我们自己使用该API连接前端和后端&#xff0c;因此您可以编写Metabase几乎可以执行的所有操作。 警告&#xff1a;MetabaseAPI可能会更改 开始之前有两个注意事项&#xff1a; API可能会更改。API与前端…

软件测试要学会哪些东西才能拿2w+的工资?

软件开发人员的月薪达到2万还是比较轻松的&#xff0c;但是软件测试人员想要月薪过万的话&#xff0c;我认为可以从两个方面去考虑&#xff1a; 1. 一种就是项目的测试负责人&#xff1a;测试人员需要对软件的整体性能改进提出建设性方案&#xff0c;所以很多软件测试人员最终…

数据结构和算法之《栈》详解

标题&#xff1a;栈的思路及代码实现 作者&#xff1a;Ggggggtm 寄语&#xff1a;与其忙着诉苦&#xff0c;不如低头赶路&#xff0c;奋路前行&#xff0c;终将遇到一番好风景 文章目录&#xff1a; 一、栈的概念及结构 1、1 栈的概念 1、2 栈的结构 二、栈的思路及代码实现详解…

电脑技巧:推荐5个非常实用的软件

❤️作者主页&#xff1a;IT技术分享社区 ❤️作者简介&#xff1a;大家好,我是IT技术分享社区的博主&#xff0c;从事C#、Java开发九年&#xff0c;对数据库、C#、Java、前端、运维、电脑技巧等经验丰富。 ❤️个人荣誉&#xff1a; 数据库领域优质创作者&#x1f3c6;&#x…

uniapp 之使用 u-upload 组件来实现图片上传

uniapp 之使用 u-upload 组件来实现图片上传前言一、官方示例用法分析二、关闭自动上传,使用手动上传的方式,代码html 代码js 代码css 代码总结分析前言 在使用 uniapp 开发的微信小程序中使用了图片上传功能,使用了 uniapp 的图片上传组件 注意&#xff1a;我这里后端接口接收…

小程序开发平台

小程序开发平台顾名思义就是一个可以开发小程序的地方。 小程序开发平台&#xff1a;【电脑浏览器输入3M.FKW.COM了解详情】 适合群体&#xff1a;企业、机构、个体户 小程序开发方式&#xff1a; 自建——可以通过套用小程序模板&#xff0c;利用拖拽式小程序开发工具&…

某组态软件工程文件加密机制探究

某组态软件工程文件加密机制探究 前言 在工业自动化控制领域&#xff0c;组态软件是数据采集与过程控制的专用软件&#xff0c;是实现人机交互必不可少的工具。工程设计人员使用组态软件在PC机上进行工程画面组态的编辑&#xff0c;然后把编译后的组态逻辑通过以太网或串口下载…

HSRP协议(思科私有)/VRRP协议(公有)

数据来源 1、HSRP热备份路由协议&#xff08;备份网关&#xff09; 出现背景&#xff1a; 如下图一个公司拉两条网线一条用来备份网关是192.168.0.253&#xff0c;平时用的网关是254&#xff0c;如果网关是254的这条网线出问题了就可以使用备份不影响公司让人员上网&#xff…

2022最新版 Java 学习线路图

第 1 阶段 - 企业级开发 - java 基础 学习掌握本阶段的内容&#xff0c;可以实现诸如迅雷下载软件、QQ 聊天客户端、中小网站&#xff0c;例如&#xff1a;小型旅游网站、小型电商网站的开发 第 2 阶段 - 企业及开发 - 基础框架 学习掌握本阶段内容&#xff0c;可以快速、规范的…

CRC校验——以SHT4xA温湿度传感器为例

CRC校验——以SHT4xA温湿度传感器为例一、简介二、计算方法&#xff08;一&#xff09;步骤&#xff08;二&#xff09;参考代码&#xff08;C语言&#xff09;&#xff08;三&#xff09;检验&#xff1a;CRC(0xBEEF) 0x92三、参考一、简介 循环冗余校验码&#xff08;CRC&am…

[附源码]计算机毕业设计JAVA疫情防控下高校教职工健康信息管理系统

[附源码]计算机毕业设计JAVA疫情防控下高校教职工健康信息管理系统 项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&…