⛳ Java 反射
目录
- ⛳ Java 反射
- 🎨 一、反射概述
- **🎃 使用反射的前提条件: **
- 🎲 类正常加载过程如下图:
- 反射优缺点:
- 🧸 Java反射机制提供的功能:
- **🥅 反射主要API**
- 🏭 二、反射的使用
- 🎯 2.1、`class`类概述
- 🎒 2.2、得到`Class`的实例
- 📐 2.3、`Java`内置 9 大 `Class`实例
- 📢 2.4、获取类中的构造器
- ✨ 2.5、调用构造器创建对象
- 🚜 2.6、获取类中的成员变量并调用(setAccessible)
- 批量获取的方法:
- 获取单个的方法:
- 设置字段的值:
- 👣 2.7、获取类中的成员方法并调用
- 获取单个的方法:
- 调用方法:
- 🐾 2.8、反射方法的其他使用之通过反射运行配置文件内容
- 🎈 2.9、反射方法的其它使用之越过泛型检查
- 🎁 三、反射面试题
⛳ Java 反射
🎨 一、反射概述
Reflection(反射)是Java被视为动态语言的关键,反射机制允许程序在执行期借助
Reflection API
获取任何类的内部信息,并直接操作任意对象的内部属性及方法。
JAVA
反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java
语言的反射机制。
**🎃 使用反射的前提条件: **
必须先得到代表的字节码的Class,Class类用于表示.class文件(字节码),原因是要想解剖一个类,必须先要获取到该类的字节码文件对象。而解剖使用的就是Class类中的方法.所以先要获取到每一个字节码文件对应的Class类型的对象。
🎲 类正常加载过程如下图:
加载完类之后, 在堆内存的方法区中就产生了一个Class类型的对象( 一个类只有一个Class对象) , 这个对象就包含了完整的类的结构信息。 我们可以通过这个对象看到类的结构。 这个对象就像一面镜子, 透过这个镜子看到类的结构, 所以, 我们形象的称之为: 反射。
反射优缺点:
- 优点
- 可以在运行程序的过程中,操作这些对象。
- 可以降低耦合度,提高程序的可扩展性。
- 缺点
- 反射很强大,但是消耗性能。主要是为了做工具和框架使用的。
🧸 Java反射机制提供的功能:
-
- 在运行时判断任意一个对象所属的类
- 在运行时构造任意一个类的对象
- 在运行时判断任意一个类所具有的成员变量和方法
- 在运行时获取泛型信息
- 在运行时调用任意一个对象的成员变量和方法
- 在运行时处理注解
- 生成动态代理
🥅 反射主要API
-
- java.lang.Class:代表一个类
- java.lang.reflect.Method:代表类的方法
- java.lang.reflect.Field:代表类的成员变量
- java.lang.reflect.Constructor:代表类的构造器
🏭 二、反射的使用
🎯 2.1、class
类概述
在Object类中定义了以下的方法,此方法将被所有子类继承:public final Class getClass()以上的方法返回值的类型是一个Class类,此类是Java反射的源头,实际上所谓反射从程序的运行结果来看也很好理解,即:可以通过对象反射求出类的名称。
Class
类的实例表示正在运行的 Java 应用程序中的类和接口。也就是jvm中有N多的实例每个类都有该Class对象(包括基本数据类型)。Class
没有公共构造方法。Class
对象是在加载类时由 Java 虚拟机以及通过调用类加载器中的defineClass
方法自动构造的。也就是这不需要我们自己去处理创建,JVM已经帮我们创建好了。
🎒 2.2、得到Class
的实例
Student stu = new User();
,Class clz = stu.getClass();
:对象.getClass();得到对象的真实类型,因为在Object里,所以每个类都有该方法。Class<Student> clz = Student.class;
: 数据类型.class(就是一份字节码)。Class.forName(String className);
:根据一个类的全限定名来构建Class对象,Class<?> clz = Class.forName("com.gbx.Student");
,这里泛型写<?>原因是此时class不知道类,因为传的是字符串。
代码示例:
package com.gbx;public class Demo {public static void main(String[] args) {//obj.getClass()方式获取Class对象 Student stu1 = new Student();//new 产生一个Student对象,一个Class对象。Class stuClass = stu1.getClass();//获取Class对象//类名.class方式获取Class对象Class stuClass2 = Student.class;//Class.forName(String className)方式获取Class对象try {Class stuClass3 = Class.forName("com.gbx.Student");//注意此字符串必须是真实路径,就是带包名的类路径,包名.类名} catch (ClassNotFoundException e) {e.printStackTrace();}}}
注:这三种方法获取的都是同一个class对象,因为表示都是JVM中共同的一份字节码。
📐 2.3、Java
内置 9 大 Class
实例
对于对象来说,可以直接使用obj.getClass()
获取Class
实例,但是基本数据类型,就没有类的权限定名,也没有getClass
方法,那么如何使用Class
类来表示基本数据类型的Class
实例?
byte,short,int,long,char,float,double,boolean ,void
关键字,上述8种类型和void
关键字,都有class
属性。例子如下:
- 表示int的Class对象: Class clz = int.class;
- 表示boolean的Class对象: boolean.class;
- void: Class clz = void.class;
- 表示数组的Class实例:String[] sArr1 = {“A”,“C”},Class clz = String[].class;//所有具有相同元素类型和维数的数组才共享同一份字节码(Class对象);
所有的数据类型都有class属性,表示都是Class对象。
注意:
int的包装类是Integer,那么 Integer.class == int.class ?结果是false,说明是两份字节码.
Integer 和 int 不是同一种数据类型,在八大基本数据类型的包装类中都有一个常量:TYPE,TYPE表示的是该包装类对应的基本数据类型的Class实例。例子如下:
- Integer.TYPE—>int.class
- Integer.TYPE == int.class;//YES
- Integer.TYPE == Integer.class;//ERROR
📢 2.4、获取类中的构造器
-
Class类获取构造器方法:Constructor类:表示类中构造器的类型,Constructor的实例就是某一个类中的某一个构造器。
-
批量获取的方法:
-
public Constructor<?>[] getConstructors()
:该方法只能获取当前Class所表示类的public修饰的构造器。 -
public Constructor<?>[] getDeclaredConstructors()
:获取当前Class所表示类的所有的构造器,和访问权限无关。
-
-
获取单个的方法:
public Constructor<T> getConstructor(Class<?>... parameterTypes)
:获取当前Class所表示类中指定的一个public的构造器。public Constructor getDeclaredConstructor(Class<?>... parameterTypes)
:获取当前Class所表示类的所有构造器中指定的一个构造器(可以是私有、受保护、默认、公有等)。
参数parameterTypes表示:构造器参数的Class类型。如:public Student(String name),Constructor c = clz.getConstructor(String.class)
代码示例:
package com.gbx;public class Student {public Student() {System.out.println("---");}public Student(String name) {System.out.println(name);}public Student(String name, String school) {System.out.println(name + " " + school);}}
package com.gbx;public class Constructors {public static void main(String[] args) throws Exception {//1.加载Class对象Class clazz = Class.forName("com.gbx.Student");//2.获取所有公有构造器System.out.println("****所有公有构造器****");Constructor[] conArray = clazz.getConstructors();for(Constructor c : conArray){System.out.println(c);}//3.获取所有构造器System.out.println("****所有的构造器****");conArray = clazz.getDeclaredConstructors();for(Constructor c : conArray){System.out.println(c);}//3.获取单个公有无参构造器System.out.println("****获取单个公有、无参的构造器****");Constructor con = clazz.getConstructor(null);System.out.println(con);//4.获取单个指定公有构造器System.out.println("****获取单个指定的公有构造器****");con = clazz.getConstructor(String.class);System.out.println(con);//5.获取单个指定构造器System.out.println("****获取单个指定的构造器****");con = clz.getDeclaredConstructor(String.class);System.out.println(con);}}
✨ 2.5、调用构造器创建对象
常用方法: public T newInstance(Object... initargs)
:使用此 Constructor
对象表示的构造方法来创建该构造方法的声明类的新实例,并用指定的初始化参数初始化该实例,参数initargs:表示调用构造器的实际参数,返回:返回创建的实例,T表示Class所表示类的类型。
提示:如果一个类中的构造器可以直接访问,同时没有参数,那么可以直接使用Class类中的newInstance方法创建对象,public Object newInstance()
:相当于 new 类名()
代码示例:
public class newInstances {public static void main(String[] args) throws Exception {//1.加载Class对象Class<Student> clz = Student.class;//2.获取构造器Constructor<Student> c = clz.getConstructor(String.class);//3.调用构造器,创建对象Student stu1 = c.newInstance("gbx");//直接访问不带参数的构造器可以直接使用Class的newInstance()方法Student stu2 = clz.newInstance();}}
🚜 2.6、获取类中的成员变量并调用(setAccessible)
-
批量获取的方法:
Field[] getFields()
:获取当前Class所表示类的所有"公有字段"。Field[] getDeclaredFields()
:获取当前Class所表示类的所有字段,包括:私有、受保护、默认、公有。
-
获取单个的方法:
public Field getField(String fieldName)
:获取当前Class所表示类的某个"公有的"字段。public Field getDeclaredField(String fieldName)
:获取当前Class所表示类的某个字段(可以是私有的)。
-
设置字段的值:
public void set(Object obj,Object value)
参数 obj:要设置的字段所在的对象,value:要为字段设置的值
代码示例:
package com.gbx.field;public class Student {public Student(){}//**字段**//public String name;protected int age;char sex;private String phoneNum;
}
package com.gbx.field;
import java.lang.reflect.Field;
public class Fields {public static void main(String[] args) throws Exception {//1.获取Class对象Class stuClass = Class.forName("com.gbx.field.Student");//2.获取字段System.out.println("***获取所有公有的字段***");Field[] fieldArray = stuClass.getFields();for(Field f : fieldArray){System.out.println(f);}System.out.println("***获取所有的字段(包括私有、受保护、默认)***");fieldArray = stuClass.getDeclaredFields();for(Field f : fieldArray){System.out.println(f);}System.out.println("***获取某个"公有的"字段并设置字段值***");Field f = stuClass.getField("name");System.out.println(f);System.out.println("***获取私有字段并设置字段值***");f = stuClass.getDeclaredField("phoneNum");System.out.println(f);//获取构造器,调用构造器获取一个对象Object obj = stuClass.getConstructor().newInstance();//产生Student对象,相当于Student stu = new Student();//为字段设置值f.set(obj, "张三");//为Student对象中的name属性赋值,相当于stu.name = "张三"//检验Student stu = (Student)obj;System.out.println("姓名:" + stu.name); f.setAccessible(true);//Student类中的成员变量phoneNum为private,故必须解除“phoneNum”私有限定f.set(obj, "12345678900");System.out.println("电话:" + stu.phoneNum); }
}
输出:
***获取所有公有的字段***
public java.lang.String com.gbx.field.Student.name
***获取所有的字段(包括私有、受保护、默认的)***
public java.lang.String com.gbx.field.Student.name
protected int com.gbx.field.Student.age
char fanshe.com.gbx.Student.sex
private java.lang.String com.gbx.field.Student.phoneNum
***获取某个“公有的”字段并设置字段值***
public java.lang.String com.gbx.field.Student.name
姓名:张三
***获取私有字段并设置字段值***
private java.lang.String com.gbx.field.Student.phoneNum
电话:12345678900
注:Java反射机制提供的setAccessible()方法,传入true
可以取消,Java的安全检查。
👣 2.7、获取类中的成员方法并调用
-
**批量获取的方法: **
public Method[] getMethods()
:获取当前Class所表示类和继承过来的所有"公有"方法(包含了父类的方法也包含Object类)。public Method[] getDeclaredMethods()
:获取当前Class所表示类的所有成员方法,包括私有的(不包括继承的,和访问权限无关)。
-
获取单个的方法:
-
public Method getMethod(String name,Class<?>... parameterTypes)
:获取当前Class所表示类的某个"公有"方法(包括继承的)。 -
public Method getDeclaredMethod(String methodName,Class<?>... parameterTypes)
:获取当前Class所表示类的某个成员方法(不包括继承的)。参数
methodName
:方法名,Class ... parameterTypes
:形参的Class类型对象
-
-
调用方法:
public Object invoke(Object obj,Object ... args)
参数 obj:要调用方法的对象,args:调用方法时所传递的实参
代码演示:
package com.gbx.method;public class Student {//****成员方法****//public void show1(String s){System.out.println("调用公有的String参数的show1(): s = " + s);}protected void show2(){System.out.println("调用受保护的无参的show2()");}void show3(){System.out.println("调用默认的无参的show3()");}private String show4(int age){System.out.println("调用私有的且有返回值的int参数的show4(): age = " + age);return age;}
}
package com.gbx.method;import java.lang.reflect.Method;public class MethodClass {public static void main(String[] args) throws Exception {//1.获取Class对象Class stuClass = Class.forName("com.gbx.method.Student");//2.获取所有公有方法System.out.println("****获取所有”公有“方法****");Method[] methodArray = stuClass.getMethods();for(Method m : methodArray){System.out.println(m);}System.out.println("****获取所有本类方法,包括私有****");methodArray = stuClass.getDeclaredMethods();for(Method m : methodArray){System.out.println(m);}System.out.println("****获取公有的show1()方法****");Method m = stuClass.getMethod("show1", String.class);System.out.println(m);//实例化一个Student对象Object obj = stuClass.getConstructor().newInstance();//调用方法,相当于stu.show1("张三")m.invoke(obj, "张三");System.out.println("****获取私有的show4()方法****");m = stuClass.getDeclaredMethod("show4", int.class);System.out.println(m);m.setAccessible(true);//解除私有限定Object result = m.invoke(obj, 20);System.out.println("返回值:" + result);}
}
输入:
****获取所有”公有“方法****
public void com.gbx.method.Student.show1(java.lang.String)
public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException
public final void java.lang.Object.wait() throws java.lang.InterruptedException
public boolean java.lang.Object.equals(java.lang.Object)
public java.lang.String java.lang.Object.toString()
public native int java.lang.Object.hashCode()
public final native java.lang.Class java.lang.Object.getClass()
public final native void java.lang.Object.notify()
public final native void java.lang.Object.notifyAll()
****获取所有本类方法,包括私有****
public void com.gbx.method.Student.show1(java.lang.String)
private java.lang.String com.gbx.method.Student.show4(int)
protected void com.gbx.method.Student.show2()
void com.gbx.method.Student.show3()
****获取公有的show1()方法****
public void com.gbx.method.Student.show1(java.lang.String)
调用公有的String参数的show1(): s = 张三
****获取私有的show4()方法****
private java.lang.String com.gbx.method.Student.show4(int)
调用私有的且有返回值的int参数的show4(): age = 20
返回值:20
🐾 2.8、反射方法的其他使用之通过反射运行配置文件内容
Student类:
public class Student {public void show(){System.out.println("It is show()");}
}
配置文件以txt文件为例子(p.txt):
className = com.gbx.Student
methodName = show
代码示例:
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.Properties;public class Demo {public static void main(String[] args) throws Exception {//通过反射获取Class对象Class stuClass = Class.forName(getValue("className"));//"com.gbx.Student"//2获取show()方法Method m = stuClass.getMethod(getValue("methodName"));//show//3.调用show()方法m.invoke(stuClass.getConstructor().newInstance()); }//此方法接收一个key,在配置文件中获取相应的valuepublic static String getValue(String key) throws IOException{Properties p = new Properties();//获取配置文件的对象FileReader fr = new FileReader("p.txt");//获取字符输入流p.load(fr);//将流加载到配置文件对象中in.close();return p.getProperty(key);//返回根据key获取的value值}
}
优点:当我们升级这个系统时,不要Student类,而需要新写其他类时,这时只需要更改p.txt里的文件内容就可以了,代码不用改动。
🎈 2.9、反射方法的其它使用之越过泛型检查
泛型用在编译期,编译过后泛型擦除(消失),所以是可以通过反射越过泛型检查的。
例如:有一个String泛型的集合,怎样能向这个集合中添加一个Integer类型的值?
代码示例:
import java.lang.reflect.Method;
import java.util.ArrayList;public class Demo {public static void main(String[] args) throws Exception{ArrayList<String> list = new ArrayList<>();list.add("aaa");list.add("bbb");//list.add(100);//获取ArrayList的Class对象,反向的调用add()方法,添加数据Class listClass = list.getClass(); //得到 list对象的字节码对象//获取add()方法Method m = listClass.getMethod("add", Object.class);//调用add()方法m.invoke(list, 100);//遍历集合for(Object obj : list){System.out.println(obj);}}
}
输出:
aaa
bbb
100
这样说明可以通过反射越过泛型检查,向String泛型的集合中添加一个Integer类型的值。
🎁 三、反射面试题
题目:如何在不改变String内存地址的情况下,改变String的内容
正常创建:
@Test
public void test3() {String s = new String("abc"); //堆里面产生sString s1 = s; //s1s = "123";String s2 = s;System.out.println(s1.hashCode() + " " + s2.hashCode() );System.out.println(s1 == s2);
}
/**
* 结果:
* 96354 48690
* false
*/
图示:
通过反射操作String中的value属性:
@Test
public void test4() throws Exception {String s = new String("123"); //堆里面产生sString s1 = s; //s1Field vf = String.class.getDeclaredField("value");vf.setAccessible(true);char[] chars = {97, 98, 99};vf.set(s, chars);String s2 = s;System.out.println(s1.hashCode() + " " + s2.hashCode() );System.out.println(s1 == s2);/*** 结果:* 96354 96354* true**/
}
图示:
相关文章:

⛳ Java 反射
目录 ⛳ Java 反射🎨 一、反射概述**🎃 使用反射的前提条件: **🎲 类正常加载过程如下图:反射优缺点:🧸 Java反射机制提供的功能: **🥅 反射主要API** 🏭 二、反射的使用Ἲ…...
Android 13 像Settings一样开启关闭深色模式
一.背景 由于客户定制的Settings需要开启关闭深色模式,所以需要自己调用开启关闭深色模式 二.前提条件 首先应用肯定要是系统应用,并且导入framework.jar包,具体可以参考: Android 应用自动开启辅助(无障碍)功能并使用辅助(无障碍)功能_android 自动开启无障碍服务_龚礼鹏…...

微服务实战项目-学成在线-项目优化(redis缓存优化)
微服务实战项目-学成在线-项目优化(redis缓存优化) 1 优化需求 视频播放页面用户未登录也可以访问,当用户观看试学课程时需要请求服务端查询数据,接口如下: 1、根据课程id查询课程信息。 2、根据文件id查询视频信息。 这些接口在用户未认…...

IDEA 找不到项目 ‘org.springframework.boot:spring-boot-starter-parent:3.1.2‘
找不到项目 ‘org.springframework.boot:spring-boot-starter-parent:2.6.7’ 这个问题主要是因为ide的缓存导致的,我们直接清理缓存并重启ide 重启之后ide会对pom文件进行编排索引完成之后问题就没有了...

thinkphp开发的在线学习培训考试模拟考试做题练习系统带商城功能证书管理课程系统
thinkphp开发的在线学习培训考试模拟考试做题练习系统带商城功能证书管理课程系统 1、做题界面 2、前端UI的展示 3、带商城购物功能...
Android 应用冷启动优化
冷启动相关概念 应用启动概念 冷启动:首次打开app或者app彻底销毁后再次打开app(开关机后),这也是我们进行启动速度优化的主要方向。热启动:应用运行中按home键再打开应用。温启动:介于两者之间ÿ…...

538页21万字数字政府智慧政务大数据云平台项目建设方案WORD
导读:原文《538页21万字数字政府智慧政务大数据云平台项目建设方案WORD》(获取来源见文尾),本文精选其中精华及架构部分,逻辑清晰、内容完整,为快速形成售前方案提供参考。 根据业务的不同属性,…...

进程间通信——信号
信号的概念 信号是 Linux进程间通信的最古老的方式之一,是事件发生时对进程的通知机制,有时也称之为软件中断,它是在软件层次上对中断机制的一种模拟,是一种异步通信的方式。信号可以导致一个正在运行的进程被另一个正在运行的异…...
PAT 1039 Course List for Student
个人学习记录,代码难免不尽人意。 Zhejiang University has 40000 students and provides 2500 courses. Now given the student name lists of all the courses, you are supposed to output the registered course list for each student who comes for a query. …...
【Sklearn】基于决策树算法的数据分类预测(Excel可直接替换数据)
【Sklearn】基于决策树算法的数据分类预测(Excel可直接替换数据) 1.模型原理1.1 模型原理1.2 数学模型2.模型参数3.文件结构4.Excel数据5.下载地址6.完整代码7.运行结果1.模型原理 决策树是一种基于树状结构的分类和回归模型,它通过一系列的决策规则来将数据划分为不同的类…...

并发编程4:Java 中的并发基础构建模块
目录 1、同步容器类 1.1 - 同步容器类的问题 1.2 - 迭代和容器加锁 2、并发容器类 2.1 - ConcurrentHashMap 类 2.2 - CopyOnWriteArrayList 类 3、阻塞队列和生产者-消费者模式 3.1 - 串行线程封闭 4、阻塞方法与中断方法 5、同步工具类 5.1 - 闭锁 -> CountDow…...

Vue-10.集成(.editorconfig、.eslintrc.js、.prettierrc)
介绍 同时使用 .editorconfig、.prettierrc 和 .eslintrc.js 是很常见的做法,因为它们可以在不同层面上帮助确保代码的格式一致性和质量。这种组合可以在开发过程中提供全面的代码维护和质量保证。然而,这也可能增加一些复杂性,需要谨慎配置…...
PHP-FPM进程排查
1、查看php-fpm的进程个数 ps -ef |grep "php-fpm"|grep "pool"|wc -l2、查看每个php-fpm占用的内存大小 ps -ylC php-fpm --sort:rss3.查看PHP-FPM在你的机器上的平均内存占用 ps --no-headers -o "rss,cmd" -C php-fpm | awk { sum$1 } END…...

PHP-MD5注入
0x00 前言 有些零散的知识未曾关注过,偶然捡起反而更加欢喜。 0x01 md5 注入绕过 md5函数有两个参数,第一个参数是要进行md5的值,第二个值默认为false,如果为true则返回16位原始二进制格式的字符串。意思就是会将md5后的结果当…...
对redis、redisson、springcache总结
<一> redis-缓存中间件 什么是redis redis是c语言开发的,一个高性能key-value键值对内存数据库,可以用来做数据库、缓存、消息中间件的一种非关系型数据库。 redis数据存储在哪里 内存和磁盘中,但是redis的读写都在内存中,…...

Java基础知识实际应用(学生信息管理系统、猜拳小游戏、打印日历)
一、Java学生信息管理系统 这个系统包含了添加、修改、删除、查询和显示所有学生信息等功能。您可以在此基础上进行修改和完善,以适应您的需求。 import java.util.Scanner;public class StudentManagementSystem {private static Scanner scanner new Scanner(S…...

Git:在本地电脑上如何使用git?
git 版本: 2.40.1.windows.1 文章目录 一. 使用git之前你必须要理解的几个概念1.1 理解工作区、版本库、暂存区的概念1.2 提交Git版本库的步骤【分两步执行】 二. Git本地库实战2.1 初始化版本库2.2 新建 & 提交 & 状态2.3 查看日志2.4 回退 & 穿梭 &am…...
卷和分区的关系
1、分区 存储空间管理和仓库管理类似,只不过仓库管理的是货物,存储空间管理的是文件。当仓库规模小时,可以不划分货物的存放区域,但当仓库规模很大,就必须根据货物的类型和存储需要,把仓库分为多个区域。例…...

Linux下在qtcreator中创建qt程序
目录 1、新建项目 2、单工程项目创建 3、多工程项目创建 4、添加子工程(基于多工程目录结构) 5、 .pro文件 1、新建项目 切换到“编辑”界面,点击菜单栏中的“文件”-“新建文件或项目” 2、单工程项目创建 只有一个工程的项目&#…...

快递再多也不怕!你的顺丰快递用上5G“神器”
互联网时代,剁手党疯狂“买买买”之后,快递件量再创新高。《2023年6月中国快递发展指数报告》显示,2023二季度单月快递业务量稳定在百亿件以上。其中,由于“618”电商促销活动与父亲节叠加,6月16日至20日单日揽收量均超…...
后进先出(LIFO)详解
LIFO 是 Last In, First Out 的缩写,中文译为后进先出。这是一种数据结构的工作原则,类似于一摞盘子或一叠书本: 最后放进去的元素最先出来 -想象往筒状容器里放盘子: (1)你放进的最后一个盘子(…...

国防科技大学计算机基础课程笔记02信息编码
1.机内码和国标码 国标码就是我们非常熟悉的这个GB2312,但是因为都是16进制,因此这个了16进制的数据既可以翻译成为这个机器码,也可以翻译成为这个国标码,所以这个时候很容易会出现这个歧义的情况; 因此,我们的这个国…...

基于FPGA的PID算法学习———实现PID比例控制算法
基于FPGA的PID算法学习 前言一、PID算法分析二、PID仿真分析1. PID代码2.PI代码3.P代码4.顶层5.测试文件6.仿真波形 总结 前言 学习内容:参考网站: PID算法控制 PID即:Proportional(比例)、Integral(积分&…...

【OSG学习笔记】Day 18: 碰撞检测与物理交互
物理引擎(Physics Engine) 物理引擎 是一种通过计算机模拟物理规律(如力学、碰撞、重力、流体动力学等)的软件工具或库。 它的核心目标是在虚拟环境中逼真地模拟物体的运动和交互,广泛应用于 游戏开发、动画制作、虚…...
在鸿蒙HarmonyOS 5中实现抖音风格的点赞功能
下面我将详细介绍如何使用HarmonyOS SDK在HarmonyOS 5中实现类似抖音的点赞功能,包括动画效果、数据同步和交互优化。 1. 基础点赞功能实现 1.1 创建数据模型 // VideoModel.ets export class VideoModel {id: string "";title: string ""…...
Golang dig框架与GraphQL的完美结合
将 Go 的 Dig 依赖注入框架与 GraphQL 结合使用,可以显著提升应用程序的可维护性、可测试性以及灵活性。 Dig 是一个强大的依赖注入容器,能够帮助开发者更好地管理复杂的依赖关系,而 GraphQL 则是一种用于 API 的查询语言,能够提…...
生成 Git SSH 证书
🔑 1. 生成 SSH 密钥对 在终端(Windows 使用 Git Bash,Mac/Linux 使用 Terminal)执行命令: ssh-keygen -t rsa -b 4096 -C "your_emailexample.com" 参数说明: -t rsa&#x…...
Spring AI与Spring Modulith核心技术解析
Spring AI核心架构解析 Spring AI(https://spring.io/projects/spring-ai)作为Spring生态中的AI集成框架,其核心设计理念是通过模块化架构降低AI应用的开发复杂度。与Python生态中的LangChain/LlamaIndex等工具类似,但特别为多语…...
#Uniapp篇:chrome调试unapp适配
chrome调试设备----使用Android模拟机开发调试移动端页面 Chrome://inspect/#devices MuMu模拟器Edge浏览器:Android原生APP嵌入的H5页面元素定位 chrome://inspect/#devices uniapp单位适配 根路径下 postcss.config.js 需要装这些插件 “postcss”: “^8.5.…...
4. TypeScript 类型推断与类型组合
一、类型推断 (一) 什么是类型推断 TypeScript 的类型推断会根据变量、函数返回值、对象和数组的赋值和使用方式,自动确定它们的类型。 这一特性减少了显式类型注解的需要,在保持类型安全的同时简化了代码。通过分析上下文和初始值,TypeSc…...