Java基础(二十三):反射(reflection)

文章目录

  • 一、反射机制
    • 1.1 快速入门
    • 1.2 反射机制原理
  • 二、反射相关类
  • 三、反射调用性能优化
  • 四、Class类
    • 4.1 基本介绍
    • 4.2 使用
    • 4.3 哪些类型有Class对象
  • 五、类加载
  • 六、获取类的结构信息
  • 七、反射-创建实例、操作属性和方法(爆破)


一、反射机制

1.1 快速入门

通过外部配置文件,在不修改源码的情况下,来控制程序,符合设计模式的ocp原则(开闭原则:不修改源码,扩容功能)
配置文件re.properties

classfullpath=ReflectionExercise.Cat
method=hi

Cat类

package ReflectionExercise;public class Cat {private String name = "招财猫";public int age = 10;public Cat(){}public Cat(String name) {this.name = name;}public void hi(){System.out.println("喵喵1");}public void cry(){System.out.println("喵喵2");}
}

实操

package ReflectionExercise;import java.io.FileInputStream;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Properties;/*** @author 神代言* @version 1.0*/
public class RefelctionQuestion {public static void main(String[] args) throws IOException, ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {// 反射机制的优点:要实现调用Cat的hi方法 变成 调用cry方法//     传统方法:cat.hi() -> cat.cry()//     反射机制:直接修改配置文件的method=hi -> method=cry,不用修改源码// 理解反射//    例:从re.properties配置文件中实现方法的调用Properties properties = new Properties();properties.load(new FileInputStream("src\\re.properties"));String classfullpath = properties.get("classfullpath").toString();String methodName = properties.get("method").toString();System.out.println("classfullpath = " + classfullpath);System.out.println("method = " + methodName);//(1)加载类Class cls = Class.forName(classfullpath);//(2)得到加载类的 对象实例oObject o = cls.newInstance();System.out.println("运行类型:" + o.getClass());//(3)得到加载类的对象实例的 方法对象method//    即:在反射中,方法可以视为对象Method method = cls.getMethod(methodName);//(4)通过 方法对象method 实现调用方法//    传统:对象.方法()//    反射:方法.invoke(对象)method.invoke(o);}
}

1.2 反射机制原理

  1. 反射机制允许程序在执行期借助于ReflectionAPI取得任何类的内部信息(比如成员变量,构造器,成员方法等等),并能操作对象的属性及方法。反射在设计模式和框架底层都会用到。
  2. 加载完类之后,在堆中就产生了一个Class类型的对象(一个类只有一个Class对象),这个对象包含了类的完整结构信息。通过这个对象得到类的结构。这个对象就像一面镜子,透过这个镜子看到类的结构,所以,形象的称之为反射。

反射机制原理图
在这里插入图片描述


二、反射相关类

在这里插入图片描述
实操

package ReflectionExercise;import java.io.FileInputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Properties;/*** @author 神代言* @version 1.0*/
public class Reflection01 {public static void main(String[] args) throws Exception{Properties properties = new Properties();properties.load(new FileInputStream("src\\re.properties"));String classfullpath = properties.get("classfullpath").toString();String methodName = properties.get("method").toString();//(1)Class:加载类Class cls = Class.forName(classfullpath);// 得到加载类的 对象实例oObject o = cls.newInstance();System.out.println("运行类型:" + o.getClass());//(2)Method:得到加载类的对象实例的 方法对象method//    即:在反射中,方法可以视为对象Method method = cls.getMethod(methodName);// 通过 方法对象method 实现调用方法//    传统:对象.方法()//    反射:方法.invoke(对象)method.invoke(o);//(3)Field: getField不能得到私有成员变量Field age = cls.getField("age");System.out.println(age.get(o));//(4)ConstructorConstructor constructor1 = cls.getConstructor();// 无参构造System.out.println(constructor1);Constructor constructor2 = cls.getConstructor(String.class);//有参构造System.out.println(constructor2);}
}输出:
运行类型:class ReflectionExercise.Cat
喵喵1
10
public ReflectionExercise.Cat()
public ReflectionExercise.Cat(java.lang.String)

三、反射调用性能优化

反射优点和缺点:
优点: 可以动态的创建和使用对象(也是框架底层核心),使用灵活,没有反射机制,框架技术就失去底层支撑。
缺点: 使用反射基本是解释执行,对执行速度有影响。

反射调用优化-关闭访问检查

  1. Method和Field、Constructor对象都有setAccessible()方法;
  2. setAccessible作用是启动和禁用访问安全检查的开关;
  3. 参数值为true表示反射的对象在使用时取消访问检查,提高反射的效率;数值为false则表示反射的对象执行访问检查。

四、Class类

4.1 基本介绍

  1. Class也是类,因此也继承Object类
  2. Class类对象不是new出来的,而是系统创建的
  3. 对于某个类的Class类对象,在内存中只有一份,因为类只加载一次
  4. 每个类的实例都会记得自己是由哪个 Class 实例所生成
  5. 通过Class对象可以完整地得到一个类的完整结构,通过一系列API
  6. Class对象是存放在堆的
  7. 类的字节码二进制数据,是放在方法区的,有的地方称为类的元数据(包括 方法代码变量名,方法名,访问权限等等)

4.2 使用

package ReflectionExercise;import java.lang.reflect.Field;/*** @author 神代言* @version 1.0*/
public class Class01 {public static void main(String[] args) throws Exception {// 一、Class类常用方法String classAllPath = "ReflectionExercise.Cat";Class cls = Class.forName(classAllPath);System.out.println("Class对象 " + cls);System.out.println("运行类型 " + cls.getClasses());System.out.println("包名 " + cls.getPackage().getName());System.out.println("全类名 " + cls.getName());// 创建实例Cat cat = (Cat)cls.newInstance();System.out.println("cat的toString " + cat);// 通过反射获取属性Field name = cls.getField("name");System.out.println("获取属性 " + name.get(cat));name.set(cat,"叮当猫");System.out.println("修改属性 " + name.get(cat));Field[] fields = cls.getFields();for (Field f: fields) {System.out.println("属性 " + f.getName());}// 二、获取Class类对象的方式// 1.前提: 已知一个类的全类名,且该类在类路径下,// 可通过Class类的静态方法forName()获取,可能抛出ClassNotFoundException,// 实例: Class cls1 =Class.forName( "java.lang.Cat);// 应用场景:多用于配置文件,读取类全路径,加载类String path = "ReflectionExercise.Cat";Class cls1 = Class.forName(path);System.out.println(cls1);// 2.前提:若已知具体的类,通过类的class 获取,// 该方式 最为安全可靠,程序性能最高// 实例:Class cls2 = Cat.class;// 应用场景:多用于参数传递,比如通过反射得到对应构造器对象Class cls2 = Cat.class;System.out.println(cls2);// 3.前提: 已知某个类的实例,调用该实例的getClass()方法获取Class对象,// 实例:Class cls3 = 对象.getClass();// 应用场景: 通过创建好的对象,获取Class对象Cat cat1 = new Cat();Class cls3 = cat1.getClass();System.out.println(cls3);// 4.类加载器// ClassLoader cl = 对象.getClass().getClassLoader();// Class cls4 = cl.loadClass(“类的全类名”);ClassLoader cl = cat1.getClass().getClassLoader();Class cls4 = cl.loadClass(path);System.out.println(cls4);// 5.基本数据(int,char,boolean,float,double,byte,long,short)// 按如下方式得到Class类对象// Class cls = 基本数据类型.classClass<Integer> cls5 = int.class;System.out.println(cls5);// 6.基本数据类型对应的包装类,可以通过 .type 得到Class类对象// Class cls = 包装类.TYPEClass<Integer> cls6 = Integer.TYPE;System.out.println(cls6);// 这几种方式[1-4][5-6]创建的的都是同一个Class对象System.out.println(cls1.hashCode());System.out.println(cls2.hashCode());System.out.println(cls3.hashCode());System.out.println(cls4.hashCode());System.out.println(cls5.hashCode());System.out.println(cls6.hashCode());}
}

运行结果

Class对象 class ReflectionExercise.Cat
运行类型 [Ljava.lang.Class;@2503dbd3
包名 ReflectionExercise
全类名 ReflectionExercise.Cat
cat的toString Cat{name='招财猫', age=10}
获取属性 招财猫
修改属性 叮当猫
属性 name
属性 age
class ReflectionExercise.Cat
class ReflectionExercise.Cat
class ReflectionExercise.Cat
class ReflectionExercise.Cat
int
int
1265094477
1265094477
1265094477
1265094477
312714112
312714112

4.3 哪些类型有Class对象

  1. 外部类,成员内部类,静态内部类,局部内部类,匿名内部类
  2. interface:接口
  3. 数组
  4. enum:枚举
  5. annotation:注解
  6. 基本数据类型
  7. void

在这里插入图片描述


五、类加载

反射机制是java实现动态语言的关键,也就是通过反射实现类动态加载

  1. 静态加载:编译时加载相关的类,如果没有则报错,依赖性太强
  2. 动态加载:运行时加载需要的类,如果运行时不用该类,则不报错,降低了依赖性

举例说明
在这里插入图片描述

类加载时机

  1. 当创建对象时 (new) // 静态加载
  2. 当子类被加载时,父类也加载 // 静态加载
  3. 调用类中的静态成员时 // 静态加载
  4. 通过反射 // 动态加载

类加载流程图
在这里插入图片描述

在这里插入图片描述

  1. 加载阶段:
    JVM 在该阶段的主要目的是将字节码从不同的数据源(可能是 class 文件、也可能是 jar 包,甚至网络)转化为二进制字节流加载到内存中,并生成一个代表该类的 java.lang.Class 对象。
  2. 连接阶段-验证:
    1)目的是为了确保 Class 文件的字节流中包含的信息符合当前虚拟机的要求,并且不会危害虚拟机自身的安全;
    2)包括: 文件格式验证(是否以魔数 oxcafebabe开头)、元数据验证、字节码验证和符号引用验证;
    3)可以考虑使用 -Xverify:none 参数来关闭大部分的类验证措施,缩短虚拟机类加载的时间。
  3. 连接阶段-准备:
    JVM 会在该阶段对静态变量分配内存并初始化(对应数据类型的默认初始值,如 0、0L、null、false 等) 。这些变量所使用的内存都将在方法区中进行分配。
    在这里插入图片描述
  4. 连接阶段-解析:
    虚拟机将常量池内的 符号引用 替换为 直接引用 的过程
  5. Initialization (初始化):
    1)到初始化阶段,才真正开始执行类中定义的 Java 程序代码,此阶段是执行< clinit >() 方法的过程。
    2)< clinit >()方法是由编译器按语句在源文件中出现的顺序,依次自动收集类中的所有静态变量的赋值动作和静态代码块中的语句,并进行合并
    3)虚拟机会保证一个类的 < clinit >() 方法在多线程环境中被正确地加锁、同步,如果多个线程同时去初始化一个类,那么只会有一个线程去执行这个类的 < clinit >()方法,其他线程都需要阻塞等待,直到活动线程执行 < clinit >() 方法完毕。

六、获取类的结构信息

Class、Field、Method、Constructor

package ReflectionExercise;import org.junit.jupiter.api.Test;import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;/*** @author 神代言* @version 1.0*/
public class ReflectionUtils {public static void main(String[] args) throws Exception{ReflectionUtils reflectionUtils = new ReflectionUtils();reflectionUtils.api_01();reflectionUtils.api_02();reflectionUtils.api_03();reflectionUtils.api_04();}@Testpublic void api_01() throws Exception {System.out.println("------第一组java.lang.Class------");Class<?> personClass = Class.forName("ReflectionExercise.Person");System.out.println(personClass.getName());System.out.println(personClass.getSimpleName());Field[] fields1 = personClass.getFields();for (Field field : fields1) {System.out.println("本类和父类的public属性:" + field.getName());}Field[] fields2 = personClass.getDeclaredFields();for (Field field : fields2) {System.out.println("本类的所有属性:" + field.getName());}Method[] methods1 = personClass.getMethods();for (Method method : methods1) {System.out.println("本类和父类的public方法:" + method.getName());}Method[] methods2 = personClass.getDeclaredMethods();for (Method method : methods2) {System.out.println("本类的所有方法:" + method.getName());}Constructor<?>[] constructors1 = personClass.getConstructors();for (Constructor<?> constructor : constructors1) {System.out.println("本类的public构造器:" + constructor.getName());}Constructor<?>[] constructors2 = personClass.getDeclaredConstructors();for (Constructor<?> constructor : constructors2) {System.out.println("本类的所有构造器:" + constructor.getName());}System.out.println("包名:" + personClass.getPackage());System.out.println("父类的class对象:" + personClass.getSuperclass());Class<?>[] interfaces = personClass.getInterfaces();for (Class<?> anInterface : interfaces) {System.out.println("接口:" + anInterface);}Annotation[] annotations = personClass.getAnnotations();for (Annotation annotation : annotations) {System.out.println("注解:" + annotation);}}@Testpublic void api_02() throws Exception {System.out.println("------第二组java.lang.reflect.Field------");Class<?> personClass = Class.forName("ReflectionExercise.Person");Field[] fields2 = personClass.getDeclaredFields();// 说明:默认修饰符是0,public是1,private是2,protected是4//       static是8,final是16for (Field field : fields2) {System.out.println("本类的所有属性名字:" + field.getName()+ " 该属性的修饰符的值:" + field.getModifiers()+ " 该属性的类型:" + field.getType());}}@Testpublic void api_03() throws Exception {System.out.println("------第二组java.lang.reflect.Method------");Class<?> personClass = Class.forName("ReflectionExercise.Person");Method[] methods2 = personClass.getDeclaredMethods();// 说明:默认修饰符是0,public是1,private是2,protected是4//       static是8,final是16for (Method method : methods2) {System.out.println("本类的所有方法:" + method.getName()+ " 该方法的修饰符的值:" + method.getModifiers()+ " 该方法的返回类型:" + method.getReturnType());Class<?>[] parameterTypes = method.getParameterTypes();for (Class<?> parameterType : parameterTypes) {System.out.println("该方法的形参类型:" + parameterType);}System.out.println("-------------");}}@Testpublic void api_04() throws Exception {System.out.println("------第二组java.lang.reflect.Constructor------");Class<?> personClass = Class.forName("ReflectionExercise.Person");Constructor<?>[] constructors2 = personClass.getDeclaredConstructors();for (Constructor<?> constructor : constructors2) {System.out.println("本类的所有构造器:" + constructor.getName());Class<?>[] parameterTypes = constructor.getParameterTypes();for (Class<?> parameterType : parameterTypes) {System.out.println("该构造器的形参类型:" + parameterType);}System.out.println("-------------");}}
}class A {public String hobby;public void hi() {}public A() {}
}interface IA {
}interface IB {
}class Person extends A implements IA, IB {public String name;protected int age;String job;private double sal;public Person() {}public Person(String name) {}private Person(String name, int age) {}public void m1(String name) {}protected void m2(String name, int age) {}void m3() {}private void m4() {}
}

运行结果

------第一组java.lang.Class------
ReflectionExercise.Person
Person
本类和父类的public属性:name
本类和父类的public属性:hobby
本类的所有属性:name
本类的所有属性:age
本类的所有属性:job
本类的所有属性:sal
本类和父类的public方法:m1
本类和父类的public方法:hi
本类和父类的public方法:wait
本类和父类的public方法:wait
本类和父类的public方法:wait
本类和父类的public方法:equals
本类和父类的public方法:toString
本类和父类的public方法:hashCode
本类和父类的public方法:getClass
本类和父类的public方法:notify
本类和父类的public方法:notifyAll
本类的所有方法:m4
本类的所有方法:m3
本类的所有方法:m2
本类的所有方法:m1
本类的public构造器:ReflectionExercise.Person
本类的public构造器:ReflectionExercise.Person
本类的所有构造器:ReflectionExercise.Person
本类的所有构造器:ReflectionExercise.Person
本类的所有构造器:ReflectionExercise.Person
包名:package ReflectionExercise
父类的class对象:class ReflectionExercise.A
接口:interface ReflectionExercise.IA
接口:interface ReflectionExercise.IB
------第二组java.lang.reflect.Field------
本类的所有属性名字:name 该属性的修饰符的值:1 该属性的类型:class java.lang.String
本类的所有属性名字:age 该属性的修饰符的值:4 该属性的类型:int
本类的所有属性名字:job 该属性的修饰符的值:0 该属性的类型:class java.lang.String
本类的所有属性名字:sal 该属性的修饰符的值:2 该属性的类型:double
------第二组java.lang.reflect.Method------
本类的所有方法:m4 该方法的修饰符的值:2 该方法的返回类型:void
-------------
本类的所有方法:m3 该方法的修饰符的值:0 该方法的返回类型:void
-------------
本类的所有方法:m2 该方法的修饰符的值:4 该方法的返回类型:void
该方法的形参类型:class java.lang.String
该方法的形参类型:int
-------------
本类的所有方法:m1 该方法的修饰符的值:1 该方法的返回类型:void
该方法的形参类型:class java.lang.String
-------------
------第二组java.lang.reflect.Constructor------
本类的所有构造器:ReflectionExercise.Person
该构造器的形参类型:class java.lang.String
该构造器的形参类型:int
-------------
本类的所有构造器:ReflectionExercise.Person
该构造器的形参类型:class java.lang.String
-------------
本类的所有构造器:ReflectionExercise.Person
-------------

七、反射-创建实例、操作属性和方法(爆破)

package ReflectionExercise;import org.junit.jupiter.api.Test;import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;/*** @author 神代言* @version 1.0*/
public class Reflection03 {public static void main(String[] args) throws Exception {Reflection03 reflection03 = new Reflection03();reflection03.CreateInstance();reflection03.accessProperty();reflection03.accessMethod();}@Testpublic void CreateInstance() throws Exception {System.out.println("------通过反射创建实例-------");Class<?> userClass = Class.forName("ReflectionExercise.User");// 1.无参构造创建实例Object o = userClass.newInstance();System.out.println(o);// 2.public有参构造创建实例/*public User(String name){this.name = name;}*/Constructor<?> constructor1 = userClass.getConstructor(String.class);Object hsp = constructor1.newInstance("hsp");System.out.println(hsp);// 3.public有参构造创建实例/*private User(int age,String name){this.age = age;this.name = name;}*/Constructor<?> constructor2 = userClass.getDeclaredConstructor(int.class, String.class);constructor2.setAccessible(true);// 爆破:操作私有private构造器Object o1 = constructor2.newInstance(12, "小黑");System.out.println(o1);}@Testpublic void accessProperty() throws Exception {System.out.println("------通过反射操作属性-------");Class<?> userClass = Class.forName("ReflectionExercise.User");Object o = userClass.newInstance();System.out.println(o);// 操作public属性Field age = userClass.getField("age");age.set(o, 88);// 操作private属性Field name = userClass.getDeclaredField("name");name.setAccessible(true);// 爆破:操作私有private属性name.set(o, "张三丰");// name.set(null,"张无忌");// 静态属性,o可以写成nullSystem.out.println(o);}@Testpublic void accessMethod() throws Exception {System.out.println("------通过反射操作方法-------");Class<?> userClass = Class.forName("ReflectionExercise.User");Object o = userClass.newInstance();System.out.println(o);// 操作public方法Method hi = userClass.getMethod("hi",String.class);hi.invoke(o,"赵敏");// 操作private方法Method declaredMethod = userClass.getDeclaredMethod("say",int.class,String.class,char.class);declaredMethod.setAccessible(true);//   因为该方法为static,因此o也可以写成nullSystem.out.println(declaredMethod.invoke(o,1000,"太上老君",'男'));}
}class User {public int age;private static String name = "万某人";public User() {}public User(String name) {this.name = name;}private User(int age, String name) {this.age = age;this.name = name;}private static String say(int n, String s, char c) {return n + " " + s + " " + c;}public void hi(String s) {System.out.println("hi " + s);}@Overridepublic String toString() {return "User{" +"age=" + age +", name='" + name + '\'' +'}';}
}

运行结果

------通过反射创建实例-------
User{age=0, name='万某人'}
User{age=0, name='hsp'}
User{age=12, name='小黑'}
------通过反射操作属性-------
User{age=0, name='小黑'}
User{age=88, name='张三丰'}
------通过反射操作方法-------
User{age=0, name='张三丰'}
hi 赵敏
1000 太上老君 男

特别说明
本文章是个人整理的学习笔记,参考b站韩顺平老师的课程(【零基础 快速学Java】韩顺平 零基础30天学会Java)。老师讲的非常好,有兴趣的可以去看一下。

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

自然语言处理应用(三):微调BERT

微调BERT 微调&#xff08;Fine-tuning&#xff09;BERT是指在预训练的BERT模型基础上&#xff0c;使用特定领域或任务相关的数据对其进行进一步训练以适应具体任务的需求。BERT&#xff08;Bidirectional Encoder Representations from Transformers&#xff09;是一种基于Tr…

【强化学习篇】on-policy 和 off-policy 的区别

本质区别&#xff1a; 要学习的 agent 跟和环境互动的 agent 是同一个&#xff0c;是on-policy(同策略) 要学习的 agent 跟和环境互动的 agent 不是同一个&#xff0c;是off-policy(异策略) on-policy 与 off-policy值函数&#xff1a; on-policy与off-policy区别是&#xf…

MCU软核 2. Xilinx Artix7上运行tinyriscv

0. 环境 - ubuntu18 - win10 vivado 2018.3 - git desktop - XC7A35TV12核心板 - ft2232hl小板&#xff08;用于程序烧录&#xff09; 1. git克隆源码 Git Desktop -> File -> Clone repository -> -> URL: https://gitee.com/liangkangnan/tinyriscv/ -> Lo…

如何在Python爬虫程序中使用HTTP代理?

在进行网络爬虫时&#xff0c;我们经常需要使用代理服务器来隐藏自己的真实IP地址&#xff0c;以避免被目标网站封禁或限制访问。本文将介绍如何将HTTP代理配置到Python爬虫程序中使用。 什么是HTTP代理&#xff1f; HTTP代理是一种网络代理&#xff0c;它充当客户端和服务器之…

Redis-带你深入学习数据类型zset

目录 1、zset有序集合 2、zset相关命令 2.1、添加或更新指定的元素——zadd 2.2、获取有序集合zset的元素个数相关命令&#xff1a;zcard、zcount 2.3、返回指定区间元素相关命令&#xff1a;zrange、arevrange、zrangebyscore 2.4、删除相关命令&#xff1a;zpopmax、zp…

$ref赋值之后,子组件不渲染(刷新后,$ref父组件传值,子组件不更新数据问题)

在父组件中&#xff0c;点击搜索&#xff0c; 通过this.$refs传值给子组件 this.$refs.GoodsClassNav.paramsAll.keyword key; 子组件结果中不显示&#xff0c; 但是打印this.$refs.GoodsClassNav.paramsAll.keyword&#xff0c;可以打印到最新的值&#xff0c;点击子组件中…

PyQt5通过堆叠布局实现选项卡(多界面)功能

PyQt5通过堆叠布局实现选项卡(多界面)功能 1、创建一个MainWindow 加入Text Brower做标题&#xff0c;几个按钮。 然后在左侧containers中添加Stacked Widget这个控件&#xff0c;初步布局如下&#xff1a; 对窗口中的堆叠容器 “Stacked Widget”&#xff0c;选中后可以用…

【100天精通Python】Day61:Python 数据分析_Pandas可视化功能:绘制饼图,箱线图,散点图,散点图矩阵,热力图,面积图等(示例+代码)

目录 1 Pandas 可视化功能 2 Pandas绘图实例 2.1 绘制线图 2.2 绘制柱状图 2.3 绘制随机散点图 2.4 绘制饼图 2.5 绘制箱线图A 2.6 绘制箱线图B 2.7 绘制散点图矩阵 2.8 绘制面积图 2.9 绘制热力图 2.10 绘制核密度估计图 1 Pandas 可视化功能 pandas是一个强大的数…

常驻巨噬细胞诱导的纤维化在胰腺炎性损伤和PDAC中具有不同的作用

介绍一篇2023年8月10日发表在Nature Immunology的文章 标题&#xff1a; Fibrosis induced by resident macrophages has divergent roles in pancreas inflammatory injury and PDAC 影响因子&#xff1a;30.5 DOI&#xff1a;https://doi.org/10.1038/s41590-023-01579-x …

web端动效 PAG

之前写过一篇lottie动效的文章&#xff1a;web端动效 lottie-web 使用&#xff0c;本篇写一下PAG-web的基础使用。 PAG是腾讯开发&#xff0c;支持移动端、桌面端以及Web端的动效工作流解决方案。目标是降低或消除动效相关的研发成本&#xff0c;能够一键将设计师在 AE&#x…

TensorFlow 03(Keras)

一、tf.keras tf.keras是TensorFlow 2.0的高阶API接口&#xff0c;为TensorFlow的代码提供了新的风格和设计模式&#xff0c;大大提升了TF代码的简洁性和复用性&#xff0c;官方也推荐使用tf.keras来进行模型设计和开发。 1.1 tf.keras中常用模块 如下表所示: 1.2 常用方法 …

Ei Scopus检索 | 2024年第四届能源与环境工程国际会议(CoEEE 2024)

会议简介 Brief Introduction 2024年第四届能源与环境工程国际会议(CoEEE 2024) 会议时间&#xff1a;2023年5月22日-24日 召开地点&#xff1a;意大利米兰 大会官网&#xff1a;www.coeee.org CoEEE 2024将围绕“能源与环境工程”的最新研究领域而展开&#xff0c;为研究人员、…

VSCODE 使用技巧

vscode批量去掉代码中空行的方法 1、在vscode中使用ctrl f组合快捷键打开替换窗口. 2、输入下面的正则表达式 ^\s*(?\r?$)\n https://mp.weixin.qq.com/s/ZKV2sZWszxBLNTNLEWhsng

springboot redisTemplate.opsForValue().setIfAbsent返回null原理

一、版本 springboot版本&#xff1a;spring-boot-starter-data-redis 2.1.6 redisson版本&#xff1a;redisson-spring-boot-starter 3.11.5 二、场景 Boolean res redisTemplate.opsForValue().setIfAbsent("key","value");以上代码同一时间多次执行…

Sentinel控制台配置 持久化到nacos

sentinel控制台&#xff0c;使用方便&#xff0c;功能强大。使用官方的jar包&#xff0c;配置不会持久化&#xff0c;sentinel重启后会导致&#xff0c;之前的规则全部丢失&#xff0c;下面一起改造源码实现规则数据的持久化 sentinel源码地址 &#xff08;github访问太慢&am…

嵌入式学习笔记(25)串口通信的基本原理

三根通信线&#xff1a;Tx Rx GND &#xff08;1&#xff09;任何通信都要有信息作为传输载体&#xff0c;或者有线的或则无线的。 &#xff08;2&#xff09;串口通信时有线通信&#xff0c;是通过串口线来通信的。 &#xff08;3&#xff09;串口通信最少需要2根&#xff…

MCU芯片测试:性能指标测试痛点是什么?ATECLOUD能否解决?

MCU芯片测试指标的核心是性能指标&#xff0c;包括处理器性能、存储器容量和读写速度&#xff0c;外设性能等。芯片测试对自动化测试的要求很高&#xff0c;ATECLOUD-IC不仅解决了传统测试方法的问题&#xff0c;而且也可以满足芯片测试的高要求&#xff0c;高效地完成MCU芯片性…

ChartJS使用-环境搭建(vue)

1、介绍 Chartjs简约不简单的JavaScript的图表库。官网https://chart.nodejs.cn/ Chart.js 带有内置的 TypeScript 类型&#xff0c;并与所有流行的 JavaScript 框架 兼容&#xff0c;包括 React 、Vue 、Svelte 和 Angular 。 你可以直接使用 Chart.js 或利用维护良好的封装程…

SpringBoot课堂笔记20230913

本篇文章为SpringBoot学习笔记&#xff0c;方便自己再复习。 Maven&#xff1a;jar包管理工具 注解&#xff1a; Controller:处理http请求&#xff0c;返回的视图 RestController: 相当于ResponseBody和Controller一起用&#xff0c;返回的是json ResponseBody:返回响应内容 …

自动化监控系统PrometheusGrafana

Prometheus 算是一个全能型选手&#xff0c;原生支持容器监控&#xff0c;当然监控传统应用也不是吃干饭的&#xff0c;所以就是容器和非容器他都支持&#xff0c;所有的监控系统都具备这个流程&#xff0c;数据采集→数据处理→数据存储→数据展示→告警 Prometheus 特点展开…