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

Java进阶-反射

来学习一下Java的反射,通过Class实例获取class信息的方法称为反射(Reflection),内容如下
在这里插入图片描述

一、反射机制

1、概述

在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为 Java 语言的反射机制。

简单来说,反射机制指的是程序在运行时能够获取自身的信息。

在 Java 中,只要给定类的名字,就可以通过反射机制来获得类的所有信息

2、应用举例

应用1:在服务器端,往往需要根据客户的请求,动态调用某一个对象的特定方法。
应用2:在 ORM 中间件的实现中,运用 Java 反射机制可以读取任意一个 JavaBean 的所有属性,或者给这些属性赋值。
反射就像是我们正常思维的一个逆过程,如下

正常方式:引入包类名称---->new实例化---->实例化对象

反射方式:实例化对象---->getClass()方法---->包类名称

3、功能及优缺点

3.1 功能

在运行期(java.lang.reflect包),
1)判断任意一个对象所属的类。
2)构造任意一个类的对象。
3)判断任意一个类所具有的成员变量和方法。
4)调用任意一个对象的方法。
5)生成动态代理。

3.2 优缺点

1)优点

能够运行时动态获取类的实例,大大提高系统的灵活性和扩展性。

与 Java 动态编译相结合,可以实现非常强大的功能。

对于 Java 这种先编译再运行的语言,能够很方便的创建灵活的代码(可以在运行时装配,无需在组件之间进行源代码的链接,更加容易实现面向对象)

2)缺点

反射会消耗一定的系统资源(如果不需要动态地创建一个对象,就不需要用反射)

反射调用方法时可以忽略权限检查,获取类的私有方法和属性,可能会破坏类的封装性而导致安全问题。

4、时期

先来看一下完整的Java程序运行过程

┌──────────────────┐
│    Hello.java    │<─── source code(源码)
└──────────────────┘│ compile(运行前由javac编译器编译)▼
┌──────────────────┐
│   Hello.class<─── byte code(字节码)
└──────────────────┘│ execute(运行时由java即JVM解释器解释)▼
┌──────────────────┐
│ Run on JVM(运行在各平台虚拟机)
└──────────────────┘
4.1 编译器

1)编译期执行过程

源码----(编译器编译)---->可执行文件(如Hello.java---->Hello.class)。

注:编译期只是做了一些翻译功能,并没有把代码放在内存中运行,只是把代码当成文本进行操作,比如检查错误。

4.2 运行期

1)运行期执行过程
把编译后的文件(.class文件)交给计算机执行,直到程序运行结束(由JVM解释器解释 .class字节码文件,运行在各平台虚拟机上)。

可执行文件----(解释器解释)---->在各平台虚拟机上运行。

简单而言,运行期就是把在磁盘中的代码放到内存中跑起来。

5、API

所谓API,就是Java自己提供的标准类库,开发人员可直接使用其方法。

5.1 java.lang.Class类

1)概述

  • 是反射机制API的核心类。
  • Class实例:一种数据类型(如类、接口、注解、数组、基本数据类型和void),由JVM在类加载时自动创建的。

2)获取Class实例 (3种方法)

  • 类名.class:通过类名的属性class获取。(多用于参数的传递)
  • 对象.getClass():通过实例变量的getClass()方法,getClass()方法在Object类中定义着,即所有对象皆有此方法。(多用于对象的获取字节码的方式)
  • Class.forName(“全类名”):将字节码文件加载进内存,返回Class对象。如Class.forName(“java.lang.String”)。

注:全类名即包名.类名(多用于配置文件,将类名定义在配置文件中。读取文件,加载类)

3)Class实例的唯一性
Class实例在JVM中是唯一的,可以用==比较两个Class实例

结论:同一个字节码文件(*.class)在一次程序运行过程中,只会被加载一次,不论通过哪一种方式获取的class对象都是同一个。

4)Class实例比较和 instanceof的区别

  • instanceof不但匹配指定类型,还匹配指定类型的子类。而用==判断class实例可以精确地判断数据类型,但不能作子类型比较。
  • 通常情况下用 instanceof判断数据类型,因为面向抽象编程不关心具体的子类型。只有在需要精确判断一个类型是不是某个class的时候,我们才使用==判断class实例。

5)示例

// java.lang包由系统自动加载,无需导包
public class ClassDemo { // 反射获取Class实例public static void main(String[] args) {Class clz1 = String.class; // 1.通过类型class静态变量---->(类型.class)String str = "Hello"; //创建(实例化)字符串对象Class clz2 = str.getClass(); // 2.通过对象的getClass()方法---->(对象.getClass())Class clz3 = int.class; // 获得int类型Class实例Class clz4 = Integer.class; // 获得Integer类型(基本类型的包装类)Class实例System.out.println(clz1.equals(clz2)); //判断两种方法获取同一类型的Class实例是否相等System.out.println("clz1类名称:" + clz1.getName()); //调用Class实例的方法(会用即可,不用死记)System.out.println("clz2类名称:" + clz2.getName());System.out.println("clz2是否为接口:" + clz2.isInterface());System.out.println("clz2是否为数组对象:" + clz2.isArray());System.out.println("clz2父类名称:" + clz2.getSuperclass().getName());System.out.println("clz2是否为基本类型:" + clz2.isPrimitive());System.out.println("clz3是否为基本类型:" + clz3.isPrimitive());System.out.println("clz4是否为基本类型:" + clz4.isPrimitive());}
}

运行结果

true
clz1类名称:java.lang.String
clz2类名称:java.lang.String
clz2是否为接口:false
clz2是否为数组对象:false
clz2父类名称:java.lang.Object
clz2是否为基本类型:false
clz3是否为基本类型:true
clz4是否为基本类型:false

注:关于基本类型的判断,String为引用类型,int为基本类型。Integer为基本类型的包装类,是类,为引用类型。

总结:除基本类型外的为引用类型,引用类型有三种:数组、类、接口。不清楚的可以回去复习。

5.2 java.lang.reflect包

1)概述

  • 所有实现反射机制的类所在的包。
  • reflect包的主要类
    • Constructor 类:提供类的构造方法信息。
    • Field 类:提供类或接口中成员变量信息。
    • Method 类:提供类或接口成员方法信息。
    • Array 类:提供了动态创建和访问 Java 数组的方法。
    • odifier 类:提供类和成员访问修饰符信息。

2)示例(了解)

import java.lang.reflect.Method; //导包
import java.lang.reflect.Modifier;public class ReflectDemo {public static void main(String[] args) {try {Class c = Class.forName("java.lang.String"); // 动态加载xx类的运行时对象(forName(String)方法)Method[] methods = c.getDeclaredMethods(); // 获取成员方法集合for (Method method : methods) { // 遍历成员方法集合System.out.print(Modifier.toString(method.getModifiers())); // 打印权限修饰符,如public、protected、privateSystem.out.print(" " + method.getReturnType().getName() + " "); // 打印返回值类型名称System.out.println(method.getName() + "();"); // 打印方法名称}} catch (ClassNotFoundException e) {System.out.println("找不到指定类");}}
}

结果比较长,有兴趣的可以自己去运行一下。

二、反射访问

1、访问构造方法

1)创建 Constructor 类型的对象或数组的方法

  • getConstructors()
  • getConstructor(Class<?>…parameterTypes)
  • getDeclaredConstructors()
  • getDeclaredConstructor(Class<?>…parameterTypes)

2)访问指定的构造方法,需根据该构造方法入口参数的类型来访问

objectClass.getDeclaredConstructor(int.class,String.class); //访问int和String类型
objectClass.getDeclaredConstructor(new Class[]{int.class,String.class});

3)Constructor 类的常用方法

查看API文档,了解不用死背。

  • isVarArgs():查看该构造方法是否允许带可变数量的参数
  • getParameterTypes():按照声明顺序以 Class 数组的形式获取该构造方法各个参数的类型
  • getExceptionTypes():以 Class 数组的形式获取该构造方法可能抛出的异常类型
  • newInstance(Object … initargs):通过该构造方法利用指定参数创建一个该类型的对象,如果未设置参数则表示采用默认无参的构造方法
  • setAccessiable(boolean flag):如果该构造方法的权限为 private,默认为不允许通过反射利用 netlnstance()方法创建对象。如果先执行该方法,并将入口参数设置为 true,则允许创建对象
  • getModifiers():获得可以解析出该构造方法所采用修饰符的整数

4)java.lang.reflect.Modifer类

Modifer英文翻译为修饰符,Modifer类常用静态方法,即查看是否被指定修饰符修饰。

  • isStatic(int mod):判断是否使用static修饰符,以下同理分析
  • isPublic(int mod)
  • isProtected(int mod)
  • isPrivate(int mod)
  • isFinal(int mod)
  • toString(int mod):以字符串形式返回所有修饰符

5)示例
使用Constructor类的方法获取构造方法的信息。
5.1)创建一个图书信息的Book类

public class Book { // 定义Book类String name; // 封装成员变量int id,price;public Book(){ // 无参构造方法}public Book(String name,int id){ // 带两个参数的构造方法this.name=name; // this指向当前变量this.id=id;}//带可变参数构造方法:允许在调用方法时传入不定长度的参数//格式:方法名(类型...数组名)      ...表示可以接受多个参数值public Book(String... strings) throws NumberFormatException{if(0<strings.length) //至少有一个参数id=Integer.valueOf(strings[0]); //将id转换为包装类型Integer//Integer.valueOf()方法可以将int或String转换为包装类型Integerif(1<strings.length) //至少有两个参数price=Integer.valueOf(strings[1]);}// 输出图书信息public void print() {System.out.println("name=" + name);System.out.println("id=" + id);System.out.println("price=" + price);}
}

5.2)创建测试类

import java.lang.reflect.Constructor; // 导包public class BookDemo { //测试类public static void main(String[] args) {// 获取动态类BookClass book = Book.class;// 获取Book类的所有构造方法(返回一个数组)Constructor[] declaredContructors = book.getDeclaredConstructors();// 遍历所有构造方法(for循环遍历数组)for (int i = 0; i < declaredContructors.length; i++) {Constructor con = declaredContructors[i];// 判断构造方法的参数是否可变System.out.println("查看是否允许带可变数量的参数:" + con.isVarArgs());System.out.println("该构造方法的入口参数类型依次为:");// 获取所有参数类型Class[] parameterTypes = con.getParameterTypes();for (int j = 0; j < parameterTypes.length; j++) {System.out.println(" " + parameterTypes[j]);}System.out.println("该构造方法可能拋出的异常类型为:");// 获取所有可能拋出的异常类型Class[] exceptionTypes = con.getExceptionTypes();for (int j = 0; j < exceptionTypes.length; j++) {System.out.println(" " + parameterTypes[j]);}// 创建一个未实例化的Book类实例Book book1 = null;while (book1 == null) {try { // 如果该成员变量的访问权限为private,则拋出异常if (i == 1) {// 通过执行带两个参数的构造方法实例化book1book1 = (Book) con.newInstance("Java 教程", 10);} else if (i == 2) {// 通过执行默认构造方法实例化book1book1 = (Book) con.newInstance();} else {// 通过执行可变数量参数的构造方法实例化book1Object[] parameters = new Object[] { new String[] { "100", "200" } };book1 = (Book) con.newInstance(parameters);}} catch (Exception e) {System.out.println("在创建对象时拋出异常,下面执行 setAccessible() 方法");con.setAccessible(true); // 设置允许访问 private 成员}}book1.print();System.out.println("=============================\n");}}
}

运行结果

查看是否允许带可变数量的参数:true
该构造方法的入口参数类型依次为:class [Ljava.lang.String;
该构造方法可能拋出的异常类型为:class [Ljava.lang.String;
name=null
id=100
price=200
=============================查看是否允许带可变数量的参数:false
该构造方法的入口参数类型依次为:class java.lang.Stringint
该构造方法可能拋出的异常类型为:
name=Java 教程
id=10
price=0
=============================查看是否允许带可变数量的参数:false
该构造方法的入口参数类型依次为:
该构造方法可能拋出的异常类型为:
name=null
id=0
price=0
=============================

2、访问方法

1)创建Method 类型的对象或数组的方法(动态获取一个对象方法信息的前提)

  • getMethods()
  • getMethods(String name,Class<?> …parameterTypes)
  • getDeclaredMethods()
  • getDeclaredMethods(String name,Class<?>…parameterTypes)

2)Method类常用方法(和Constructor 类的常用方法类似,可查看API文档或源码,不再赘述)
3)示例
使用Method类的方法获取动态类中方法的信息
3.1)创建一个Book1类,编写4个不同作用域的方法。

public class Book1 { //创建Book1类static void staticMethod(){ // static作用域方法System.out.println("执行staticMethod()方法");}public int publicMethod(int i){ // public作用域方法System.out.println("执行publicMethod()方法");return 100+i;}// protected作用域方法protected int protectedMethod(String s,int i) throws NumberFormatException{//NumberFormatException:数字格式化异常,一般是类型错误System.out.println("执行protectedMethod()方法");return Integer.valueOf(s)+i; //Integer.valueOf()方法:可以将String或int类型转换为包装类型Integer}private String privateMethod(String...strings){ // private作用域方法System.out.println("执行privateMethod()方法");StringBuffer sb=new StringBuffer();for (int i=0;i<sb.length();i++){sb.append(strings[i]);}return sb.toString(); //将StringBuffer转换为String类型}
}

3.2)创建测试类

import java.lang.reflect.Method; //导包public class Book1_Test { //创建测试类public static void main(String[] args){// 获取动态类Book1Book1 book=new Book1();Class class1=book.getClass();// 获取Book1类的所有方法,返回一个数组,遍历结果Method[] declaredMethods=class1.getDeclaredMethods();for(int i=0;i<declaredMethods.length;i++){Method method=declaredMethods[i];System.out.println("方法名称为:"+method.getName());System.out.println("方法是否带有可变数量的参数:"+method.isVarArgs());System.out.println("方法的参数类型依次为:");// 获取所有参数类型,返回一个数组Class[] methodType=method.getParameterTypes();for(int j=0;j<methodType.length;j++){ //参数类型在方法里面,所以用双重循环System.out.println(" "+methodType[j]);}System.out.println("方法的返回值类型为:"+method.getReturnType());// 获取返回值类型System.out.println("方法可能抛出的异常类型有:");// 获取所有可能抛出的异常,返回一个数组Class[] methodExceptions=method.getExceptionTypes();for(int j=0;j<methodExceptions.length;j++){System.out.println(" "+methodExceptions[j]);}boolean isTurn=true;while(isTurn){try{ // 如果该成员变量的访问权限为private,则抛出异常isTurn=false;if(method.getName().equals("staticMethod")){ // 调用没有参数的方法method.invoke(book);} else if (method.getName().equals("publicMethod")) { // 调用一个参数的方法System.out.println("publicMethod(10)的返回值为:" + method.invoke(book, 10));} else if (method.getName().equals("protectedMethod")) { // 调用两个参数的方法System.out.println("protectedMethod(\"10\",15)的返回值为:" + method.invoke(book, "10", 15));} else if (method.getName().equals("privateMethod")) { // 调用可变数量参数的方法Object[] parameters = new Object[] { new String[] { "J", "A", "V", "A" } };System.out.println("privateMethod()的返回值为:" + method.invoke(book, parameters));}}catch (Exception e){System.out.println("在设置成员变量值时抛出异常,下面执行setAccessible()方法");method.setAccessible(true);isTurn=true;}}System.out.println("=============================\n");}}
}

运行结果

方法名称为:staticMethod
方法是否带有可变数量的参数:false
方法的参数类型依次为:
方法的返回值类型为:void
方法可能抛出的异常类型有:
执行staticMethod()方法
=============================方法名称为:publicMethod
方法是否带有可变数量的参数:false
方法的参数类型依次为:int
方法的返回值类型为:int
方法可能抛出的异常类型有:
执行publicMethod()方法
publicMethod(10)的返回值为:110
=============================方法名称为:privateMethod
方法是否带有可变数量的参数:true
方法的参数类型依次为:class [Ljava.lang.String;
方法的返回值类型为:class java.lang.String
方法可能抛出的异常类型有:
在设置成员变量值时抛出异常,下面执行setAccessible()方法
执行privateMethod()方法
privateMethod()的返回值为:
=============================方法名称为:protectedMethod
方法是否带有可变数量的参数:false
方法的参数类型依次为:class java.lang.Stringint
方法的返回值类型为:int
方法可能抛出的异常类型有:class java.lang.NumberFormatException
执行protectedMethod()方法
protectedMethod("10",15)的返回值为:25
=============================

3、访问成员变量

1)访问成员变量的方法

  • getFields():获取所有public修饰的成员变量 - - - getField(String name)
  • getDeclaredFields():获取所有成员变量,不考虑修饰符
  • getDeclaredField(String name)

2)Field 类的常用方法(很多,查看API文档或源码)

getName()    获得该成员变量的名称
getType()    获取表示该成员变量的 Class 对象
get(Object obj)    获得指定对象 obj 中成员变量的值,返回值为 Object 类型
set(Object obj, Object value)    将指定对象 obj 中成员变量的值设置为 value
getlnt(0bject obj)    获得指定对象 obj 中成员类型为 int 的成员变量的值
setlnt(0bject obj, int i)    将指定对象 obj 中成员变量的值设置为 i
setFloat(Object obj, float f)    将指定对象 obj 中成员变量的值设置为 f
getBoolean(Object obj)    获得指定对象 obj 中成员类型为 boolean 的成员变量的值
setBoolean(Object obj, boolean b)    将指定对象 obj 中成员变量的值设置为 b
getFloat(Object obj)    获得指定对象 obj 中成员类型为 float 的成员变量的值
setAccessible(boolean flag)    此方法可以设置是否忽略权限直接访问 private 等私有权限的成员变量
setAccessible(true):暴力反射,忽略访问权限修饰符的安全检查
getModifiers()    获得可以解析出该方法所采用修饰符的整数

3)示例
3.1)创建一个Book2类

public class Book2 { // 创建一个Book2类String name; //默认修饰public int id;private float price;protected boolean isLoan;
}

3.2)创建测试类

import java.lang.reflect.Field; //导包public class Book2_Test {public static void main(String[] args) {Book2 book = new Book2();// 获取动态类Book2Class class1 = book.getClass();// 获取Book2类的所有成员,返回一个数组Field[] declaredFields = class1.getDeclaredFields();// 遍历所有的成员for(int i = 0;i < declaredFields.length;i++) {// 获取类中的成员变量Field field = declaredFields[i];System.out.println("成员名称为:" + field.getName());Class fieldType = field.getType();System.out.println("成员类型为:" + fieldType);boolean isTurn = true;while(isTurn) {try {// 如果该成员变量的访问权限为private,则抛出异常isTurn = false;System.out.println("修改前成员的值为:" + field.get(book));// 判断成员类型是否为intif(fieldType.equals(int.class)) {System.out.println("利用setInt()方法修改成员的值");field.setInt(book, 100);} else if(fieldType.equals(float.class)) {// 判断成员变量类型是否为floatSystem.out.println("利用setFloat()方法修改成员的值");field.setFloat(book, 29.815f);} else if(fieldType.equals(boolean.class)) {// 判断成员变量是否为booleanSystem.out.println("利用setBoolean()方法修改成员的值");field.setBoolean(book, true);} else {System.out.println("利用set()方法修改成员的值");field.set(book, "Java编程");}System.out.println("修改后成员的值为:" + field.get(book));} catch (Exception e) {System.out.println("在设置成员变量值时抛出异常,下面执行setAccessible()方法");field.setAccessible(true);isTurn = true;}}System.out.println("=============================\n");}}
}

运行结果

成员名称为:name
成员类型为:class java.lang.String
修改前成员的值为:null
利用set()方法修改成员的值
修改后成员的值为:Java编程
=============================成员名称为:id
成员类型为:int
修改前成员的值为:0
利用setInt()方法修改成员的值
修改后成员的值为:100
=============================成员名称为:price
成员类型为:float
在设置成员变量值时抛出异常,下面执行setAccessible()方法
修改前成员的值为:0.0
利用setFloat()方法修改成员的值
修改后成员的值为:29.815
=============================成员名称为:isLoan
成员类型为:boolean
修改前成员的值为:false
利用setBoolean()方法修改成员的值
修改后成员的值为:true
=============================

相关文章:

Java进阶-反射

来学习一下Java的反射&#xff0c;通过Class实例获取class信息的方法称为反射&#xff08;Reflection&#xff09;&#xff0c;内容如下 一、反射机制 1、概述 在运行状态中&#xff0c;对于任意一个类&#xff0c;都能够知道这个类的所有属性和方法&#xff1b;对于任意一…...

力扣180 连续出现的数字

如何有效地识别在数据库中至少连续出现三次的数字&#xff1f; 目录 题目描述 解题思路 完整代码 进一步探索 题目描述 表&#xff1a;Logs ---------------------- | Column Name | Type | ---------------------- | id | int | | num | varch…...

C++面试 -操作系统-架构能力:内存问题分析与性能优化

内存问题分析&#xff1a; 内存泄漏&#xff1a; 描述什么是内存泄漏&#xff0c;以及它如何在 C 中发生。使用工具&#xff08;如 Valgrind、AddressSanitizer&#xff09;来检测和定位内存泄漏。如何预防内存泄漏&#xff1f;使用智能指针、正确释放资源等。 野指针和悬挂指针…...

基于springboot+vue的共享汽车管理系统(前后端分离)

博主主页&#xff1a;猫头鹰源码 博主简介&#xff1a;Java领域优质创作者、CSDN博客专家、阿里云专家博主、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战&#xff0c;欢迎高校老师\讲师\同行交流合作 ​主要内容&#xff1a;毕业设计(Javaweb项目|小程序|Pyt…...

All Roads Lead to Rome (30)

1、题目&#xff1a; Indeed there are many different tourist routes from our city to Rome. You are supposed to find your clients the route with the least cost while gaining the most happiness. Input Specification: Each input file contains one test case. For…...

GO语言学习笔记(与Java的比较学习)(四)

结构体 一个结构体&#xff08;struct&#xff09;就是一组字段&#xff08;field&#xff09;。 package main ​ import "fmt" ​ type Vertex struct {X intY int } ​ func main() {fmt.Println(Vertex{1, 2}) } 结构体中的字段用 . 访问 package main ​ im…...

在实训云平台上配置云主机

文章目录 零、学习目标一、实训云升级二、实训云登录&#xff08;一&#xff09;登录实训云&#xff08;二&#xff09;切换界面语言&#xff08;三&#xff09;规划云主机实例 三、创建网络三、创建路由器2024-2-29更新到此四、添加接口五、创建端口六、添加安全组规则七、创建…...

什么是隔离式栅极驱动器?

在电子设备领域&#xff0c;“驱动”一词占据着至关重要的地位&#xff0c;充当推动信号、控制和电源的力量。这个复杂世界中的一个重要组件是隔离式栅极驱动器&#xff0c;这项技术在确保各种电子系统高效、安全运行方面发挥着关键作用。 什么是栅极驱动器&#xff1f; 从本质…...

蓝桥杯算法赛 第 6 场 小白入门赛 解题报告 | 珂学家 | 简单场 + 元宵节日快乐

前言 整体评价 因为适逢元宵节&#xff0c;所以这场以娱乐为主。 A. 元宵节快乐 题型: 签到 节日快乐&#xff0c;出题人也说出来自己的心愿, 祝大家AK快乐! import java.util.Scanner;public class Main {public static void main(String[] args) {System.out.println(&qu…...

附加Numpy数组

参考&#xff1a;Append Numpy Array 引言 在数据科学和机器学习领域&#xff0c;处理大规模数据集是一项重要且常见的任务。为了高效地处理数据&#xff0c;numpy是一个非常强大的Python库。本文将详细介绍numpy中的一个重要操作&#xff0c;即如何附加&#xff08;append&a…...

收银系统源码-智慧新零售,ERP进销存功能详解

智慧新零售是一套线下线上一体化的收银系统&#xff0c;不仅给门店线下提供了多样化的收款方式&#xff0c;还提供了和线下深度打通的线上小程序商城。有线下又有线上自然需要一套完整的进销存模块能高效的管理商品。 智慧新零售进销存功能涵盖了商品的采购、销售、调拨、盘点…...

STM32使用PB3, PB4引脚的注意事项

STM32的PB3, PB4引脚作为GPIO引脚需要注意&#xff0c;因为他们默认分别是JTDO和NJTRST引脚。 笔者在设计可调增益增益放大器&#xff08;VGA&#xff09;的时候&#xff0c;使用4个GPIO读取外部控制电压&#xff0c;根据约定的编码格式设定DAC的输出电压&#xff0c;从而设置V…...

OSCP靶场--DVR4

OSCP靶场–DVR4 考点(1.windows&#xff1a;路径遍历获取私钥getshell 2.ssh shell中runas切换用户) 1.nmap扫描 ┌──(root㉿kali)-[~/Desktop] └─# nmap -sV -sC -p- 192.168.161.179 --min-rate 2000 Starting Nmap 7.92 ( https://nmap.org ) at 2024-02-29 07:14 EST…...

【嵌入式——QT】日期与定时器

日期 QTime&#xff1a;时间数据类型&#xff0c;仅表示时间&#xff0c;如 16:16:16&#xff1b;QDate&#xff1a;日期数据类型&#xff0c;仅表示日期&#xff0c;如2024-1-22&#xff1b;QDateTime&#xff1a;日期时间数据类型&#xff0c;表示日期和时间&#xff0c;如2…...

如何决定使用HashMap还是TreeMap?

使用 HashMap 还是 TreeMap 取决于你的需求和对数据结构的理解。 HashMap&#xff1a; 快速插入和查找&#xff1a;HashMap 提供了常数时间&#xff08;O(1)&#xff09;的插入和查找操作&#xff0c;因此对于需要快速插入和查找的场景非常适用。无序性&#xff1a;HashMap 不保…...

平台工程与安全

平台工程不是为了取代DevOps&#xff0c;而是DevOps的进一步演进和发展。本文介绍了DevOps和平台工程&#xff0c;以及对于安全的意义。原文: Platform Engineering and Security: A Very Short Introduction 中国云南大理的日落 我是一名 DevOps 工程师&#xff0c;个人还是希…...

智能咖啡厅助手:人形机器人 +融合大模型,行为驱动的智能咖啡厅机器人(机器人大模型与具身智能挑战赛)

智能咖啡厅助手&#xff1a;人形机器人 融合大模型&#xff0c;行为驱动的智能咖啡厅机器人(机器人大模型与具身智能挑战赛) “机器人大模型与具身智能挑战赛”的参赛作品。的目标是结合前沿的大模型技术和具身智能技术&#xff0c;开发能在模拟的咖啡厅场景中承担服务员角色并…...

js处理IOS虚拟键盘弹出后输入框被遮住

​ JS IOS 前言 在项目开发的过程中&#xff0c;在IOS手机端系统下&#xff0c;当对输入框&#xff08;input/textarea&#xff09;进行focus操作时&#xff0c;键盘弹起遮住输入框。 问题描述 从页面底部focus输入框失败从页面中间focus输入框失败 原因 造成上述问题的&…...

脚手架工程使用ElementUI

在终端中执行以下指令 npm install --save element-ui 在终端中显示added 9 packages in 10s 说明安装完成 在工程的main.js中 导入并使用ElementUI: import ElementUI from element-ui import element-ui/lib/theme-chalk/index.css Vue.use(ElementUI) 可以在*.vue页面中…...

163邮箱SMTP端口号及服务器地址详细设置?

163邮箱SMTP端口号是什么&#xff1f;163邮件SMTP设置教程&#xff1f; 除了基本的邮箱账号和密码外&#xff0c;还需要了解SMTP服务器地址和端口号&#xff0c;以及相应的设置。这些设置对于确保邮件能够顺利发送至关重要。下面&#xff0c;蜂邮EDM将详细介绍163邮箱SMTP端口…...

相机Camera日志实例分析之二:相机Camx【专业模式开启直方图拍照】单帧流程日志详解

【关注我&#xff0c;后续持续新增专题博文&#xff0c;谢谢&#xff01;&#xff01;&#xff01;】 上一篇我们讲了&#xff1a; 这一篇我们开始讲&#xff1a; 目录 一、场景操作步骤 二、日志基础关键字分级如下 三、场景日志如下&#xff1a; 一、场景操作步骤 操作步…...

线程与协程

1. 线程与协程 1.1. “函数调用级别”的切换、上下文切换 1. 函数调用级别的切换 “函数调用级别的切换”是指&#xff1a;像函数调用/返回一样轻量地完成任务切换。 举例说明&#xff1a; 当你在程序中写一个函数调用&#xff1a; funcA() 然后 funcA 执行完后返回&…...

c++ 面试题(1)-----深度优先搜索(DFS)实现

操作系统&#xff1a;ubuntu22.04 IDE:Visual Studio Code 编程语言&#xff1a;C11 题目描述 地上有一个 m 行 n 列的方格&#xff0c;从坐标 [0,0] 起始。一个机器人可以从某一格移动到上下左右四个格子&#xff0c;但不能进入行坐标和列坐标的数位之和大于 k 的格子。 例…...

sqlserver 根据指定字符 解析拼接字符串

DECLARE LotNo NVARCHAR(50)A,B,C DECLARE xml XML ( SELECT <x> REPLACE(LotNo, ,, </x><x>) </x> ) DECLARE ErrorCode NVARCHAR(50) -- 提取 XML 中的值 SELECT value x.value(., VARCHAR(MAX))…...

Python如何给视频添加音频和字幕

在Python中&#xff0c;给视频添加音频和字幕可以使用电影文件处理库MoviePy和字幕处理库Subtitles。下面将详细介绍如何使用这些库来实现视频的音频和字幕添加&#xff0c;包括必要的代码示例和详细解释。 环境准备 在开始之前&#xff0c;需要安装以下Python库&#xff1a;…...

Swagger和OpenApi的前世今生

Swagger与OpenAPI的关系演进是API标准化进程中的重要篇章&#xff0c;二者共同塑造了现代RESTful API的开发范式。 本期就扒一扒其技术演进的关键节点与核心逻辑&#xff1a; &#x1f504; 一、起源与初创期&#xff1a;Swagger的诞生&#xff08;2010-2014&#xff09; 核心…...

LeetCode - 199. 二叉树的右视图

题目 199. 二叉树的右视图 - 力扣&#xff08;LeetCode&#xff09; 思路 右视图是指从树的右侧看&#xff0c;对于每一层&#xff0c;只能看到该层最右边的节点。实现思路是&#xff1a; 使用深度优先搜索(DFS)按照"根-右-左"的顺序遍历树记录每个节点的深度对于…...

Python基于历史模拟方法实现投资组合风险管理的VaR与ES模型项目实战

说明&#xff1a;这是一个机器学习实战项目&#xff08;附带数据代码文档&#xff09;&#xff0c;如需数据代码文档可以直接到文章最后关注获取。 1.项目背景 在金融市场日益复杂和波动加剧的背景下&#xff0c;风险管理成为金融机构和个人投资者关注的核心议题之一。VaR&…...

【Post-process】【VBA】ETABS VBA FrameObj.GetNameList and write to EXCEL

ETABS API实战:导出框架元素数据到Excel 在结构工程师的日常工作中,经常需要从ETABS模型中提取框架元素信息进行后续分析。手动复制粘贴不仅耗时,还容易出错。今天我们来用简单的VBA代码实现自动化导出。 🎯 我们要实现什么? 一键点击,就能将ETABS中所有框架元素的基…...

算法打卡第18天

从中序与后序遍历序列构造二叉树 (力扣106题) 给定两个整数数组 inorder 和 postorder &#xff0c;其中 inorder 是二叉树的中序遍历&#xff0c; postorder 是同一棵树的后序遍历&#xff0c;请你构造并返回这颗 二叉树 。 示例 1: 输入&#xff1a;inorder [9,3,15,20,7…...