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

数据结构——反射、枚举以及lambda表达式

1. 反射

Java的反射(reflection)机制是在运⾏时检查、访问和修改类、接⼝、字段和⽅法的机制;这种动态获取信息以及动态调⽤对象⽅法的功能称为java语⾔的反射(reflection)机制。
用途
1. 框架开发
2. 注解处理
3. 动态代理
4. 配置⽂件解析
5. 等等

1. 反射相关的类

2. Class类(反射机制的起源 )

类 |API 参考 |Android 开发人员 代表类的实体,在运⾏的Java应⽤程序中表⽰类和接⼝

1. Java程序运行的生命周期

  1. 编译阶段

    • Java源代码(.java文件)经过javac编译器编译

    • 生成与平台无关的字节码文件(.class文件)

    • 字节码文件包含类的结构信息和方法指令

  2. 类加载阶段

    • JVM通过类加载器(ClassLoader)读取.class文件

    • 将字节码数据转换为JVM内部的数据结构

    • 创建对应的java.lang.Class对象

  3. Class对象的作用

    • 每个加载的类在JVM中都有唯一的Class对象

    • Class对象包含类的完整元数据:

      • 类名、修饰符、包信息

      • 字段(属性)信息

      • 方法信息

      • 构造器信息

      • 注解信息

  4. 反射机制

    • 通过Class对象可以获取类的运行时信息

    • 动态操作类的能力包括:

      • 创建类的实例

      • 调用方法和访问字段

      • 修改访问权限

      • 动态代理

2. 获得Class对象的三种⽅式

package reflection;public class Student {//私有属性private String name = "zhangshan";//公有属性public int age = 18;//不带参数的共有构造方法public Student(){System.out.println("student()");}//带一个参数的公有构造方法public Student(String name){this.name = name;System.out.println("Student(name)");}//带一个参数的私有构造方法private Student(int age){this.age = age;System.out.println("Student(age)");}//带两个参数的私有构造方法private Student(String name,int age){this.name = name;this.age = age;System.out.println("Student(name,age)");}//公有方法public void sleep(){System.out.println("I am sleepy");}//私有方法private void eat(String food){System.out.println("I love delicious food");}private void run(){System.out.println("Run fast");}@Overridepublic String toString() {return "Student{" +"name='" + name + '\'' +", age=" + age +'}';}public static void main(String[] args) {Student student = new Student();System.out.println(student);}
}
1. 使⽤ Class.forName("类的全路径名"); 静态⽅法。
前提:已明确类的全路径名。
2. 使⽤ .class ⽅法。
说明:仅适合在编译前就已经明确要操作的 Class
3. 使⽤类对象的 getClass() ⽅法; 已经加载的类的对象实例
//获得Class对象的三种⽅式
class Main {public static void main(String[] args) {//1. 通过Class.forName获取class对象Class<?> c1 = null;try{c1 = Class.forName("reflection.Student");}catch(ClassNotFoundException e){e.printStackTrace();}//2.直接通过 类名.class 的⽅式得到,该⽅法最为安全可靠,程序性能更⾼//这说明任何⼀个类都有⼀个隐含的静态成员变量 classClass<?> c2 = Student.class;//3. 通过getClass获取Class对象Student s3 = new Student();//创建对象Class<?> c3 = s3.getClass();//⼀个类在 JVM 中只会有⼀个 Class 实例,即我们对上⾯获取的//c1,c2,c3进⾏ equals ⽐较,发现都是trueSystem.out.println(c1.equals(c2));System.out.println(c1.equals(c3));System.out.println(c2.equals(c3));}
}

3. Class类中的相关⽅法

1. 获取类信息
方法返回值用途示例
Class.forName("全限定类名")Class<?>动态加载类Class.forName("java.lang.String")
对象.getClass()Class<?>获取对象的 Class 对象"hello".getClass()
类名.classClass<?>直接获取类的 Class 对象String.class
clazz.getName()String获取全限定类名(如 "java.lang.String"String.class.getName()
clazz.getSimpleName()String获取简单类名(如 "String"String.class.getSimpleName()
clazz.getPackage()Package获取包信息String.class.getPackage()
clazz.getModifiers()int获取修饰符(需用 Modifier 解析)Modifier.isPublic(modifiers)
clazz.getSuperclass()Class<?>获取父类Integer.class.getSuperclass()
clazz.getInterfaces()Class<?>[]获取实现的接口List.class.getInterfaces()
2. 常⽤获得类相关的⽅法:

3. 获取注解(Annotation)
方法返回值用途示例
clazz.getAnnotations()Annotation[]获取类上的所有注解clazz.getAnnotations()
clazz.getAnnotation(注解类)Annotation获取类上的指定注解clazz.getAnnotation(Deprecated.class)
field.getAnnotations()Annotation[]获取字段上的所有注解field.getAnnotations()
method.getAnnotations()Annotation[]获取方法上的所有注解method.getAnnotations()
constructor.getAnnotations()Annotation[]获取构造方法上的所有注解constructor.getAnnotations()
4. 获取构造方法(Constructor)
方法返回值用途示例
clazz.getDeclaredConstructors()Constructor<?>[]获取所有声明的构造方法(包括私有)clazz.getDeclaredConstructors()
clazz.getConstructors()Constructor<?>[]获取所有公共构造方法clazz.getConstructors()
clazz.getDeclaredConstructor(参数类型...)Constructor<?>获取指定参数类型的构造方法(包括私有)clazz.getDeclaredConstructor(String.class)
clazz.getConstructor(参数类型...)Constructor<?>获取指定参数类型的公共构造方法clazz.getConstructor()
constructor.setAccessible(true)void设置私有构造方法可访问constructor.setAccessible(true)
constructor.newInstance(参数...)Object通过构造方法创建实例constructor.newInstance("Tom")
5. 获取属性(Field)
方法返回值用途示例
clazz.getDeclaredFields()Field[]获取所有声明的属性(包括私有)clazz.getDeclaredFields()
clazz.getFields()Field[]获取所有公共属性(包括继承的)clazz.getFields()
clazz.getDeclaredField("name")Field获取指定名称的属性(包括私有)clazz.getDeclaredField("age")
clazz.getField("name")Field获取指定名称的公共属性clazz.getField("name")
field.setAccessible(true)void设置私有属性可访问field.setAccessible(true)
field.get(obj)Object获取属性值field.get(user)
field.set(obj, value)void设置属性值field.set(user, "Tom")

6. 获取方法(Method)
方法返回值用途示例
clazz.getDeclaredMethods()Method[]获取所有声明的方法(包括私有)clazz.getDeclaredMethods()
clazz.getMethods()Method[]获取所有公共方法(包括继承的)clazz.getMethods()
clazz.getDeclaredMethod("方法名", 参数类型...)Method获取指定方法(包括私有)clazz.getDeclaredMethod("setName", String.class)
clazz.getMethod("方法名", 参数类型...)Method获取指定公共方法clazz.getMethod("toString")
method.setAccessible(true)void设置私有方法可访问method.setAccessible(true)
method.invoke(obj, 参数...)Object调用方法method.invoke(user, "Tom")
package reflection;import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;public class Test{//类的实例化public static void reflectNewInstance(){try{Class<?> classStudent = Class.forName("reflection.Student");Object objectStudent = classStudent.newInstance();//Student student = (Student) objectStudent;System.out.println("获得学生对象:"+objectStudent);} catch (ClassNotFoundException e) {throw new RuntimeException(e);} catch (InstantiationException e) {throw new RuntimeException(e);} catch (IllegalAccessException e) {throw new RuntimeException(e);}}//获取类的公有(public)带一个参数构造方法并实例化public static void reflectPublicConstructor(){try{Class<?> classStudent = Class.forName("reflection.Student");//获取类的公有(public)无参构造方法Constructor<?> con = classStudent.getConstructor(String.class);//利用构造方法进行实例化Object studentNewInstance = con.newInstance("wangwu");//Student student = (Student) studentNewInstance;System.out.println("获得公有带一个参数构造方法并修改姓名:"+studentNewInstance);} catch (Exception e) {throw new RuntimeException(e);}}//获取类的私有(private)带一个参数构造方法并实例化public static void reflectPrivateConstructor(){try{Class<?> classStudnt = Class.forName("reflection.Student");//获取类的私有(private)带一个参数构造方法Constructor<?> con = classStudnt.getDeclaredConstructor(int.class);//绕过 Java 的访问控制检查,允许你访问或调用原本不可见的成员(如 private 构造方法、方法或字段)。con.setAccessible(true);//实例化Object studentNewInstance = con.newInstance(20);System.out.println("获得私有带一个参数构造方法并修改年龄:"+studentNewInstance);} catch (Exception e) {throw new RuntimeException(e);}}//获取类的所有构造方法并实例化public static void reflectionConstructor(){try{Class<?> classStudent = Class.forName("reflection.Student");//取类的所有构造方法Constructor<?>[] con = classStudent.getDeclaredConstructors();//使所有构造方法绕过 Java 的访问控制检查,允许访问或调用原本不可见的成员for(Constructor<?> constructor:con){constructor.setAccessible(true);}//实例化Object s1 = con[3].newInstance();Object s2 = con[0].newInstance("lihua",23);System.out.println("获得公有带一个参数构造方法并修改姓名:"+s1);System.out.println("获得私有带两个参数构造方法并修改姓名和年龄:"+s2);} catch (Exception e) {throw new RuntimeException(e);}}//获取私有属性public static void reflectPrivateField(){try {Class<?> classStudent = Class.forName("reflection.Student");//实例化Object s1 = classStudent.newInstance();//获取私有属性Field field = classStudent.getDeclaredField("name");field.setAccessible(true);//修改私有属性field.set(s1,"xh");//获取修改后的私有属性String name = (String) field.get(s1);System.out.println("修改之后的私有属性:"+name);} catch (Exception e) {throw new RuntimeException(e);}}//获取私有方法public static void reflectPrivateMethod(){try {Class<?> classStudent = Class.forName("reflection.Student");//获取私有方法Method method = classStudent.getDeclaredMethod("eat",String.class);System.out.println("获取私有⽅法的⽅法名为:"+method.getName());method.setAccessible(true);//实例化Object s1 = classStudent.newInstance();//方法调用method.invoke(s1,"vegetable");} catch (Exception e) {throw new RuntimeException(e);}}public static void main(String[] args) {reflectNewInstance();reflectPublicConstructor();reflectPrivateConstructor();reflectionConstructor();reflectPrivateField();

3. 反射优点和缺点

1. 优点

1. 动态性(运行时操作类)

  • 无需在编译时确定类,可以在运行时动态加载类、调用方法、访问属性。

2. 访问私有成员

  • 通过 setAccessible(true) 可以绕过 Java 的访问控制,访问 private 方法、属性和构造方法。

3. 泛型擦除时获取真实类型

  • 由于 Java 泛型在运行时会被擦除(Type Erasure),可以通过反射获取泛型的实际类型。

4. 注解处理

  • 反射可以读取类、方法、字段上的注解,实现灵活的配置和扩展。

5. 动态创建和操作对象

  • 可以在运行时动态创建对象、调用方法,适用于 高度灵活 的场景。

2. 缺点

大家都说 Java 反射效率低,你知道原因在哪里么_慕课手记

1. 性能较差

  • 反射比直接调用慢 10~100 倍,主要因为:

    • JVM 无法优化反射调用(如方法内联)。

    • 需要额外的安全检查(如 AccessibleObject.setAccessible())。

  • 影响场景

    • 高频调用的代码(如循环内使用反射)。

    • 高性能要求的系统(如交易系统、游戏引擎)。

2. 破坏封装性

  • setAccessible(true) 可以绕过 private 限制,导致:

    • 代码安全性降低(恶意代码可能篡改私有数据)。

    • 破坏面向对象的封装原则(如 final 字段被修改)。

3. 代码可读性和维护性差

  • 反射代码通常 冗长、难以调试,IDE 也无法提供智能提示。

4. 编译时检查失效

  • 反射调用在 编译期不会检查错误(如方法名拼写错误、参数类型不匹配),只能在运行时抛出异常。

5. 安全问题

  • 反射可以 绕过安全管理器(SecurityManager),可能导致:

    • 私有 API 被非法调用。

    • 敏感数据泄露(如通过反射获取 Password 字段)。

通过 getDeclaredMethods()getDeclaredFields() 或 getDeclaredConstructors() 获取的方法、属性或构造方法的顺序是不确定的,具体顺序取决于 JVM 的实现(如 OpenJDK 和 Oracle JDK 可能不同)。所以我们可以使用 Arrays.sort 按名称、修饰符、参数类型等自行排序。
优点缺点
动态加载和操作类性能差(比直接调用慢 10~100 倍)
可访问私有成员破坏封装性
支持泛型擦除时的类型获取代码可读性差
强大的注解处理能力编译时检查失效
适用于框架和灵活架构可能引发安全问题

2. 枚举

1. 背景及定义

枚举是在JDK1.5以后引⼊的。主要⽤途是:将⼀组常量组织起来,在这之前表⽰⼀组常量通常使⽤定义常量的⽅式:
public static final int RED = 1;
public static final int GREEN = 2;
public static final int WHITE = 3;
但是常量举例有不好的地⽅,例如:可能碰巧有个数字1,但是他有可能误会为是RED,现在我们可以直接⽤枚举来进⾏组织,这样⼀来,就拥有了类型,枚举类型。⽽不是普通的整形1
优点:将常量组织起来统⼀进⾏管理
场景:错误状态码,消息类型,颜⾊的划分,状态机等等....
本质:是 java.lang.Enum 的⼦类,也就是说,⾃⼰写的枚举类,就算没有显⽰的继承 Enum ,但 是其默认继承了这个类。

2. Enum 类的常⽤⽅法

枚举可以像普通类一样定义字段、构造方法和普通方法。此时,枚举常量必须调用相应的构造方法:

3. 关键点:

  1. 枚举常量必须放在枚举类的最前面,并用逗号 , 分隔,最后一个常量后用分号 ; ,后面才能定义字段和方法。。

  2. 枚举的构造方法是自动调用的,构造方法必须与枚举常量的参数匹配(无参常量 → 无参构造方法;带参常量 → 带参构造方法)。

  3. 构造方法默认是 private,不能声明为 public 或 protected(因为枚举的实例只能由枚举自身创建)。

  4. 构造方法调用是隐式的,当枚举类被 JVM 加载时,所有枚举常量会被初始化,并自动调用对应的构造方法(不能手动调用构造方法),例如 WHITE("White",5);

  5. 枚举常量是单例的构造方法只会被调用一次

  6. 每个枚举常量本质上是一个静态实例,相当于:

public static final EnumDom WHITE = new EnumDom("White",10);

(枚举类型(enum)的构造方法默认是私有的(private),这意味着你不能直接使用new关键字来创建枚举实例。 枚举常量必须通过枚举类型本身隐式创建。例如 WHITE("White",5);

7. 在Java中,枚举常量的引用不可变,但若设计不当(含非 final 字段),其内部状态可能被修改。强烈建议将枚举设计为完全不可变

4. 使用

public enum EnumDom {RED,//无参枚举常量GREEN("Green"),//带一个参数的枚举常量WHITE("White",5);//带两个参数的枚举常量//枚举类型(enum)的构造方法默认是私有的(private),这意味着你不能直接使用new关键字来创建枚举实例。// 枚举常量必须通过枚举类型本身隐式创建。//public static final EnumDom WHITE = new EnumDom("White",10);//构造方法必须匹配枚举常量的参数类型和数量//无参构造方法(可不写,java会自动提供)private EnumDom(){}public String name;public int code;//带一个参数的构造方法private EnumDom(String name){this.name = name;}//带两个参数的构造方法private EnumDom(String name,int code){this.name = name;this.code = code;System.out.println(this.name+" "+this.code);}//方法private void color(String name){this.name = name;//非final字段,可以修改System.out.println(this.name);}//    @Override
//    public String toString() {
//        return "EnumDom{" +
//                "name='" + name + '\'' +
//                ", code=" + code +
//                '}';
//    }public static void main(String[] args) {//直接调用枚举常量//枚举常量在类加载时通过构造方法初始化,且仅初始化一次(线程安全)。EnumDom w1 = EnumDom.WHITE;EnumDom w2 = EnumDom.WHITE;System.out.println(w1);System.out.println(w2);System.out.println(w1==w2);//同一个WHITE//以数组形式返回枚举类型的所有成员EnumDom[] enumDom = EnumDom.values();for(EnumDom e: enumDom){System.out.print(e+" ");//获取枚举成员的索引位置System.out.println(e.ordinal());}//将普通字符串转换为枚举实例EnumDom e1 = EnumDom.valueOf("RED");System.out.println(e1);//比较两个枚举成员在定义时的顺序System.out.println(enumDom[0].compareTo(enumDom[2]));//方法调用enumDom[0].color("red");enumDom[1].color("green");}
}

5. 枚举和反射

通过反射我们可以获取枚举常量本身,非final字段,方法,构造方法信息,注解信息

不可以获取/操作的内容:

  1. 无法通过构造方法创建新的枚举实例

    • 尝试反射调用构造方法会抛出IllegalArgumentException: Cannot reflectively create enum objects

  2. 无法修改final字段(除非使用特殊技巧)

    • 常规反射无法修改final字段

    • 需要先修改Field的modifiers字段(不推荐)

  3. 无法获取编译器生成的某些特殊方法

    • values()valueOf()方法在字节码中是编译器生成的

  4. 无法改变枚举常量的顺序(ordinal)

    • ordinal是final的且由编译器决定

  5. 无法删除或添加枚举常量

    • 枚举集合在运行时是固定的

package enumeration;import java.lang.reflect.Constructor;
import java.lang.reflect.Method;public class Test {public static void main(String[] args) {try{Class<?> clazz = Class.forName("enumeration.EnumDom");//获取所有枚举常量并调用对应的构造方法Object[] enumDoms = clazz.getEnumConstants();//打印所有枚举成员for(Object em :enumDoms ){System.out.println(em);}//获取枚举构造方法Constructor<?>[] con = clazz.getDeclaredConstructors();for(Constructor<?> constructor:con){constructor.setAccessible(true);}//获取指定枚举构造方法,包含继承的Enum的构造方法的参数Constructor<?> con1 = clazz.getDeclaredConstructor(String.class,int.class,String.class);//无法通过反射创建新实例//Object e1 = con[0].newInstance();//抛出异常 Cannot reflectively create enum objects//System.out.println(e1);//获取枚举类的方法Method method = clazz.getDeclaredMethod("color",String.class);method.setAccessible(true);method.invoke(EnumDom.RED,"red");//在反射中可以直接调用枚举常量method.invoke(enumDoms[1],"green");} catch (Exception e) {throw new RuntimeException(e);}}
}

3. Lambda表达式

1. 背景

Lambda表达式是Java SE 8中⼀个重要的新特性。lambda表达式允许你通过表达式来代替功能接⼝。 lambda表达式就和⽅法⼀样,它提供了⼀个正常的参数列表和⼀个使⽤这些参数的主体(body,可以是⼀个表达式或⼀个代码块)。 Lambda 表达式(Lambda expression),基于数学中的λ演算得名,也可称为闭包(Closure) 。

2. Lambda表达式的语法

(parameters) -> expression
(parameters) ->{ statements; }
Lambda表达式由三部分组成:
1. paramaters:类似⽅法中的形参列表,这⾥的参数是函数式接⼝⾥的参数(可以包含零个或多个) 。这⾥的参数类型可以明确的声明也可不声明⽽由JVM隐含的推断。另外当只有⼀个参数且无参数类型时可以省略掉圆括号。
2. ->:可理解为“被⽤于”的意思,将参数与方法体分开
3. ⽅法体:可以是单个表达式或代码块,是函数式接⼝⾥⽅法的实现。代码块可返回⼀个值或者什么都不返回,这⾥的代码块等同于⽅法的⽅法体。如果是表达式,也可以返回⼀个值或者什么都不返回。单个表达式或不用return关键字 直接返回表达式结果可以省略大括号{}。

3. 函数式接⼝

⼀个接⼝有且只有⼀个抽象⽅法 。
注意:
1. 如果⼀个接⼝只有⼀个抽象⽅法,那么该接⼝就是⼀个函数式接⼝
2. 如果我们在某个接⼝上声明了 @FunctionalInterface 注解,那么编译器就会按照函数式接⼝的定义来要求该接⼝,这样如果有两个抽象⽅法,程序编译就会报错的。所以,从某种意义上来说,只要你保证你的接⼝中只有⼀个抽象⽅法,你可以不加这个注解。加上就会⾃动进⾏检测的。
//⽆返回值⽆参数
@FunctionalInterface
interface NoParameterNoReturn {void test();
}
//⽆返回值⼀个参数
@FunctionalInterface
interface OneParameterNoReturn {void test(int a);
}
//⽆返回值多个参数
@FunctionalInterface
interface MoreParameterNoReturn {void test(int a,int b);
}
//有返回值⽆参数
@FunctionalInterface
interface NoParameterReturn {int test();
}
//有返回值⼀个参数
@FunctionalInterface
interface OneParameterReturn {int test(int a);
}
//有返回值多参数
@FunctionalInterface
interface MoreParameterReturn {int test(int a,int b);
}
public class Test {public static void main(String[] args) {//内部类NoParameterNoReturn noParameterNoReturn1 = new NoParameterNoReturn() {@Overridepublic void test() {System.out.println("⽆返回值⽆参数1");}};noParameterNoReturn1.test();NoParameterNoReturn noParameterNoReturn =()->System.out.println("⽆返回值⽆参数2");noParameterNoReturn.test();//当只有一个参数时,无参数类型,可以不需要()OneParameterNoReturn oneParameterNoReturn = x->{System.out.print("⽆返回值一个参数:");System.out.println(x);};oneParameterNoReturn.test(10);MoreParameterNoReturn moreParameterNoReturn = (x,y)->{System.out.print("⽆返回值多个参数:");System.out.println(x+y);};moreParameterNoReturn.test(10,20);//当 Lambda 体不使用 return 语句时,直接返回表达式结果不需要大括号NoParameterReturn noParameterReturn = ()->100;System.out.print("有返回值无参数:");System.out.println(noParameterReturn.test());//当 Lambda 体使用 return 语句时,必须使用大括号 {} 包裹代码块OneParameterReturn oneParameterReturn = (int x)->{return x;};System.out.print("有返回值一个参数:");System.out.println(oneParameterReturn.test(200));MoreParameterReturn moreParameterReturn = (x,y)->{System.out.print("有返回值多个参数:");return x+y;};System.out.println(moreParameterReturn.test(300,400));}
}

4. Lambda 表达式和匿名内部类

特性Lambda 表达式匿名内部类
引入版本Java 8Java 1.1
语法简洁性更简洁相对冗长
适用场景仅适用于函数式接口(单个抽象方法)适用于任何接口或抽象类
生成类文件不生成额外.class文件生成外部类$数字.class文件
this关键字含义指向外部类实例指向内部类自身实例

1. 变量捕获

Lambda 表达式可以捕获外部作用域的变量,这种特性称为"变量捕获"(Variable Capture)。这是 Lambda 表达式强大功能之一,但也需要遵循特定规则。

1. 局部变量捕获

Lambda 可以捕获方法中的局部变量,但有严格限制:

  • 被捕获的局部变量必须是 final 或 effectively final(即初始化后不再修改)

  • 原因:Lambda 可能在原始变量生命周期结束后执行,Java 需要保证值的一致性

2. 实例变量捕获

Lambda 可以自由捕获所在类的实例变量:

  • 可以读取

  • 可以修改

  • 不需要是 final

3. 静态变量捕获

Lambda 可以自由捕获静态变量:

  • 可以读取

  • 可以修改

  • 不需要是 final

变量类型可读性可修改性final要求
局部变量必须effectively final
实例变量不需要
静态变量不需要
interface Student{void fun();
}
public class Test2 {public int a = 10;//实例变量public static int b = 20;//静态变量public void fuction(){int c = 30;//局部变量Student student = ()->{a = 40;b = 50;//被捕获的局部变量必须final 或 effectively final(即初始化后不再修改)//c = 60;//err System.out.println(a);//40System.out.println(b);//50System.out.println(c);//30};student.fun();}public static void main(String[] args) {Test2 test2 = new Test2();test2.fuction();}
}

5. Lambda在集合当中的使⽤

注意:Collection的 forEach()⽅法是从接⼝ java.lang.Iterable 拿过来的。

相关文章:

数据结构——反射、枚举以及lambda表达式

1. 反射 Java的反射&#xff08;reflection&#xff09;机制是在运⾏时检查、访问和修改类、接⼝、字段和⽅法的机制&#xff1b;这种动态获取信息以及动态调⽤对象⽅法的功能称为java语⾔的反射&#xff08;reflection&#xff09;机制。 用途 1. 框架开发 2. 注解处理 3.…...

深入理解 HTML5 Web SQL 数据库:用法、现状与替代方案

一、引言 在 Web 开发的领域中,客户端存储一直是一个关键的话题。HTML5 带来了多种客户端存储的解决方案,其中 Web SQL 数据库曾经是一个备受关注的选项。尽管如今它已被废弃,但了解其原理、使用方法以及为何被替代,对于 Web 开发者来说仍然具有重要的意义。本文将深入探讨…...

系统架构设计(一):UML与软件架构

什么是系统架构设计&#xff1f; 系统架构设计是对系统高层结构和行为的描述&#xff0c;包括&#xff1a; 系统的各个模块&#xff08;组件&#xff09;模块之间的交互方式数据流动、控制流动技术选型与部署策略 系统架构常见的风格有&#xff1a; 分层架构&#xff08;La…...

极狐GitLab 外部流水线验证功能解读

极狐GitLab 是 GitLab 在中国的发行版&#xff0c;关于中文参考文档和资料有&#xff1a; 极狐GitLab 中文文档极狐GitLab 中文论坛极狐GitLab 官网 外部流水线验证 (BASIC SELF) 您可以使用外部服务在创建流水线之前进行验证。 极狐GitLab 发送一个 POST 请求到外部服务的…...

MCP和A2A是什么?

MCP和A2A是什么&#xff1f; MCP&#xff08;Model-Connect Protocol&#xff09;和A2A&#xff08;Agent-to-Agent&#xff09;协议逐渐成为行业关注的焦点。这两个协议分别由Anthropic和谷歌推出&#xff0c;旨在提升智能体与外部工具、数据源及API资源的连接效率&#xff0c…...

CNN卷积神经网络

一、什么是卷积神经网络&#xff08;CNN&#xff09; CNN&#xff08;卷积神经网络&#xff09;是一种专门用于处理图像的神经网络&#xff0c;尤其在图像识别任务中表现出色&#xff0c;例如识别手写数字。它通过多层结构逐步提取图像特征&#xff0c;最终输出识别结果。与传…...

生物信息学技能树(Bioinformatics)与学习路径

李升伟 整理 生物信息学是一门跨学科领域&#xff0c;涉及生物学、计算机科学以及统计学等多个方面。以下是关于生物信息学的学习路径及相关技能的详细介绍。 一、基础理论知识 1. 生物学基础知识 需要掌握分子生物学、遗传学、细胞生物学等相关概念。 对基因组结构、蛋白质…...

Obsidian无门槛简明教程

Obsidian简明教程 Markdown基本语法基本码字标题换行段落引用分割线代码块链接带名字的链接超链接插入图片 强调语法加粗斜体删除线高亮 列表有序列表无序列表任务列表 Obsidian核心用法软件基本使用安装仓库文件夹笔记编辑与查看 资源 核心插件双链标签 三方插件Various Compl…...

常用 Git 命令详解

Git 是一个强大的版本控制工具&#xff0c;广泛用于软件开发和团队协作中。掌握 Git 命令可以帮助开发者更高效地管理代码版本和项目进度。本文将介绍一些常用的 Git 命令&#xff0c;并提供示例以帮助你更好地理解和应用这些命令。 目录 常用命令 git clonegit stashgit pul…...

【HDFS入门】HDFS与Hadoop生态的深度集成:与YARN、MapReduce和Hive的协同工作原理

目录 引言 1 HDFS核心架构回顾 2 HDFS与YARN的集成 3 HDFS与MapReduce的协同 4 HDFS与Hive的集成 4.1 Hive架构与HDFS交互 4.2 Hive数据组织 4.3 Hive查询执行流程 5 HDFS在生态系统中的核心作用 6 性能优化实践 7 总结 引言 在大数据领域&#xff0c;Hadoop生态系统…...

多路由器通过三层交换机互相通讯(单臂路由+静态路由+默认路由版),通过三层交换机让pc端相互通讯

多路由器通过三层交换机互相通讯&#xff08;单臂路由静态路由默认路由版&#xff09; 先实现各个小框框里能够互通 哇咔 交换机1&#xff08;二层交换机,可看配置单臂路由的文章) Switch>en Switch#conf t Switch(config)#int f0/1 Switch(config-if)#switchport access…...

电控---CMSIS概览

1. CMSIS库简介 CMSIS&#xff08;Cortex Microcontroller Software Interface Standard&#xff0c;Cortex微控制器软件接口标准&#xff09;是由ARM公司开发的一套标准化软件接口&#xff0c;旨在为基于ARM Cortex-M系列处理器&#xff08;如Cortex-M0/M0/M3/M4/M7/M33等&am…...

2025.04.17【Stacked area】| 生信数据可视化:堆叠区域图深度解析

文章目录 生信数据可视化&#xff1a;堆叠区域图深度解析堆叠面积图简介为什么使用堆叠面积图如何使用R语言创建堆叠面积图安装和加载ggplot2包创建堆叠面积图的基本步骤示例代码 解读堆叠面积图堆叠面积图的局限性实际应用案例示例&#xff1a;基因表达量随时间变化 结论 生信…...

XSS之同源、跨域、内容安全策略

一、什么是同源策略 HTML的同源策略是浏览器的一个重要的安全机制&#xff0c;它用于限制一个源的网页如何与另一个源的资源进行交互&#xff0c;以此来减少夸站脚本攻击(XSS)和跨站请求伪造(CSRF)等安全风险。 同源的定义 若两个URL的协议&#xff08;protocol&#xff09;、…...

十三、系统设计

一、前言 二、架构设计概念 三、架构风格 四、面向服务的架构 五、微服务 六、MDA 七、软件界面设计 八、软件设计的构成 九、结构化设计 十、面向对象设计内容提要 十一、面向对象设计原则 十二、架构模式、设计模式与惯用法...

HTTP 2.0 协议特性详解

1. 使用二进制协议&#xff0c;简化传输的复杂性&#xff0c;提高了效率 2. 支持一个 TCP 链接发起多请求&#xff0c;移除 pipeline HTTP/2 移除了 HTTP/1.1中的管道化&#xff08;pipeline&#xff09;机制&#xff0c;转而采用多路复用&#xff08;Multiplexing&#xff0…...

MySQL数据备份

一&#xff0c;为什么要进行数据备份 备份&#xff1a;能够防止由于机械故障以及人为误操作带来的数据丢失&#xff0c;例如将数据库文件保存在了其它地方。冗余&#xff1a; 数据有多份冗余&#xff0c;但不等备份&#xff0c;只能防止机械故障带来的数据丢失&#xff0c;例如…...

【Ai】CherryStudio 详细使用:本地知识库、MCP服务器

一、CherryStudio 介绍 Cherry Studio 是一款集多模型对话、知识库管理、AI 绘画、翻译等功能于一体的全能 AI 助手平台。 Cherry Studio 高度自定义的设计、强大的扩展能力和友好的用户体验&#xff0c;使其成为专业用户和 AI 爱好者的理想选择。无论是零基础用户还是开发者&…...

STM32F103_HAL库+寄存器学习笔记17 - CAN中断接收 + 接收CAN总线所有报文

导言 如上所示&#xff0c;本实验的目的是使能CAN接收FIFO1的挂号中断&#xff0c;使用CAN过滤器0与CAN接收FIFO1的组合&#xff0c;接收CAN总线上所有的CAN报文。 如上所示&#xff0c;STM32F103有两个3级深度的接收FIFO。外设CAN想要正常接收CAN报文&#xff0c;必须配置接收…...

kafka报错:The Cluster ID doesn‘t match stored clusterId Some in meta.properties

kafka启动报错&#xff1a; ERROR Fatal error during KafkaServer startup. Prepare to shutdown (kafka.server.KafkaServer) kafka.common.InconsistentClusterIdException: The Cluster ID kVSgfurUQFGGpHMTBqBPiw doesnt match stored clusterId Some(0Qftv9yBTAmf2iDPSl…...

QML 信号与槽

QML 信号与槽 QML 是 Qt 框架中用于构建现代化、流畅用户界面的声明式语言&#xff0c;其信号与槽&#xff08;Signals and Slots&#xff09;机制是实现组件间通信和交互的核心特性。与 C 的信号与槽类似&#xff0c;QML 的信号与槽提供了一种松耦合的方式&#xff0c;允许界…...

数据结构-栈

大家好&#xff0c;今天带来的是关于数据结构初阶中的栈和队列的内容&#xff0c;一起来看看吧&#xff01;&#xff01;&#xff01; 1.栈的概念 栈&#xff1a;一种特殊的线性表&#xff0c;其只允许在固定的一端进行插入和删除元素操作。进行数据插入和删除操作的一端称为…...

Java 开发玩转 MCP:从 Claude 自动化到 Spring AI Alibaba 生态整合

摘要 本文以原理与示例结合的形式讲解 Java 开发者如何基于 Spring AI Alibaba 框架玩转 MCP&#xff0c;主要包含以下内容。 1. 一些 MCP 基础与快速体验&#xff08;熟悉的读者可以跳过此部分&#xff09; 2. 如何将自己开发的 Spring 应用发布为 MCP Server&#xff0c;验…...

CSS核心笔记001

目录 杂七杂八知识点样式优先级风格基本选择器通配符元素类ID 复合选择器交集选择器并集后代-孙子儿子兄弟属性各种属性选择器的应用 伪类动态伪类结构伪类否定伪类目标为类语言伪类UI伪类 伪元素 杂七杂八知识点 样式优先级 行内 > 内部 > 外部风格 紧凑风格基本选择…...

Windows快速切换屏幕/桌面

windows自带的切屏 需要winctrl 小键盘左右键 但是&#xff01; Windows使用还是键盘加鼠标舒服&#xff01; 教程 安装autohotkey 代码 ~LWin & LButton::{SendInput "^#{Left}" ; 发送 Win Ctrl Left (切换到左侧虚拟桌面) } ; 使用花括号包裹命令&a…...

ESP32- 开发笔记- 硬件设计-ESP32-C3基本电路

ESP32的最小电路 1 ESP32固件下载 ESP32 有多种下载(烧录)固件的方式,具体选择取决于开发环境和硬件连接。以下是常见的几种下载方式: 1.1 USB 串口下载(最常用) 适用场景:通过 USB 转串口芯片(如 CP2102、CH340)连接电脑,使用 esptool 或其他工具烧录固件。这里…...

webgl入门实例-09索引缓冲区示例

实现效果 实现代码 <!doctype html> <html lang"en"><head><meta charset"utf-8" /><meta http-equiv"X-UA-Compatible" content"IEedge" /><meta name"viewport"content"widthdevi…...

STM32 串口中断接收方式笔记:HAL_UART_Receive_IT vs __HAL_UART_ENABLE_IT

&#x1f4d8; STM32 串口中断接收方式笔记&#xff1a;HAL_UART_Receive_IT vs __HAL_UART_ENABLE_IT &#x1f9e0; 1. 两者作用简述 函数/宏作用是否配置HAL状态是否调用Rx回调HAL_UART_Receive_IT()启动一次基于中断的串口接收任务✅ 是✅ 是__HAL_UART_ENABLE_IT()手动使…...

ubuntu 向右拖动窗口后消失了、找不到了

这是目前单显示器的设置&#xff0c;因为实际只有1个显示器&#xff0c;之前的设置如下图所示&#xff0c;有2个显示器&#xff0c;一个主显示器&#xff0c;一个23寸的显示器 ubuntu 22.04 系统 今天在操作窗口时&#xff0c;向右一滑&#xff0c;发现这个窗口再也不显示了、找…...

Selenium 获取 Web 页面信息的全指南

Selenium 获取 Web 页面信息的全指南 Selenium 是一个功能强大的自动化测试工具&#xff0c;但它也可以用于 web 页面信息的抓取和分析。本文将详细介绍如何使用 Selenium 来获取网页信息&#xff0c;并涵盖从环境搭建到高级技巧的各个方面。 目录 简介环境搭建Selenium 的基…...

stm32-lm75、SPI

一、lm75--温度传感器 LM75 是一种数字温度传感器和带有 2 线接口的热监视器&#xff08;热看门狗&#xff09;&#xff0c;以下是其详细介绍&#xff1a; 一、核心功能与特点 温度检测与转换 内置带隙温度传感器和 Sigma-Delta 模数转换器&#xff0c;可实现 -55℃ 至 125℃ 温…...

介绍 Docker 的基本概念和优势,以及在应用程序开发中的实际应用。

Docker 是一种开源的容器化平台&#xff0c;可以帮助开发人员打包、部署和运行应用程序。Docker 的基本概念是利用容器来封装应用程序及其所有依赖项&#xff0c;使其能够在任何环境中快速、可靠地运行。 Docker 的优势包括&#xff1a; 轻量级和灵活性&#xff1a;Docker 容…...

如何判断单片机性能极限?

目录 1、CPU 负载 2、内存使用情况 3、实时性能 4、外设带宽 5、功耗与温度 在嵌入式系统设计中&#xff0c;当系统变得复杂、功能增加时&#xff0c;单片机可能会逐渐逼近其性能极限。及时识别这些极限点对于保证产品质量、稳定性和用户体验至关重要。 当你的嵌入式系统…...

LeetCode 2919 使数组变美的最小增量运算数

动态规划解题&#xff1a;最小操作次数使数组变为美丽数组 问题描述 给定一个下标从0开始、长度为n的整数数组nums和一个整数k。你可以对数组中的任意一个元素进行加1操作&#xff0c;操作次数不限。如果数组中任意长度大于或等于3的子数组的最大值都大于或等于k&#xff0c;…...

5.VTK 相机

文章目录 概念示例 概念 在VTK&#xff08;VisualizationToolkit&#xff09;中&#xff0c;相机&#xff08;vtkCamera&#xff09;用于定义场景的观察视角。以下是关于VTK相机的主要概念和设置方法的总结&#xff1a; 相机位置&#xff1a;通过vtkCamera::SetPosition()方法设…...

基于Flask的网络安全渗透知识库系统架构解析

基于Flask的网络安全渗透知识库系统架构解析 一、系统架构概述 本系统采用经典的三层Flask架构设计&#xff0c;通过模块化的方式实现渗透技术知识库的展示与管理。整体架构包含以下核心组件&#xff1a; 路由控制层&#xff1a;app.py作为入口文件模板展示层&#xff1a;Ji…...

Flutter BigInt 是用于处理任意精度整数的特殊数字类型,专为解决超大整数运算需求而设计

在Flutter/Dart中&#xff0c;BigInt 是用于处理任意精度整数的特殊数字类型&#xff0c;专为解决超大整数运算需求而设计。以下是从原理到实践的全面解析&#xff1a; 一、核心特性 特性说明任意精度突破普通int的64位限制&#xff08;-2^63 ~ 2^63-1&#xff09;&#xff0c…...

绿幕抠图直播软件-蓝松抠图插件--使用相机直播,灯光需要怎么打?

使用SONY相机进行绿幕抠图直播时&#xff0c;灯光布置是关键&#xff0c;直接影响抠图效果和直播画质。以下是详细的灯光方案和注意事项&#xff1a; 一、绿幕灯光布置核心原则 均匀照明&#xff1a;绿幕表面光线需均匀&#xff0c;避免阴影和反光&#xff08;亮度差控制在0.5…...

DeepSeek在数据仓库的10大应用场景

一、智能数据集成与清洗 多源数据整合&#xff1a;DeepSeek能够从多种数据源中提取、转换和加载数据&#xff0c;实现跨系统数据的高效整合。 数据清洗与标准化&#xff1a;通过智能算法自动识别并纠正数据中的错误、不一致性和缺失值&#xff0c;提升数据质量。 二、数据仓…...

Java 工厂设计模式详解:用统一入口打造灵活可扩展的登录系统----掌握 Spring 源码的基础第一步

一、前言 在实际开发中&#xff0c;我们经常面临以下场景&#xff1a; 系统支持多种登录方式&#xff08;用户名密码、管理员登录、OAuth 登录、短信登录等&#xff09; 每种登录方式的认证逻辑不同 我们希望对外提供一个统一的接口调用&#xff0c;而不暴露具体实现 这个…...

算法备案和大模型备案能否同时申请?

最近收到很多小伙伴咨询说“算法备案和大模型备案能不能同时申请&#xff1f;”也有一些小伙伴们还分不清算法备案和大模型备案的区别&#xff0c;纷纷询问做了大模型备案还需要做算法备案吗&#xff1f;今天一篇文章带大家了解一下&#xff0c;算法备案和大模型备案究竟是怎么…...

【2025“华中杯”大学生数学建模挑战赛】C题:就业状态分析与预测 详细解题思路

目录 2025“华中杯”大学生数学建模挑战赛C题 详细解题思路一、问题一1.1 问题分析1.2 数学模型 1.3 Python代码1.4 Matlab代码 二、问题二2.1 问题分析2.2 数学模型 2.3 Python代码2.4 Matlab代码 三、问题三3.1 问题分析 四、问题四4.1 问题分析与数学模型 2025“华中杯”大学…...

纷析云开源财务软件:助力企业财务管理数字化转型

在当今数字化时代&#xff0c;企业对财务管理工具的需求日益增长&#xff0c;而开源软件以其透明性、灵活性和成本优势成为越来越多企业的选择。纷析云开源财务软件作为一款专注于企业财务数字化的开源解决方案&#xff0c;不仅提供了强大的功能支持&#xff0c;还通过开源生态…...

APang网联科技项目报告(服务器域管理篇)

APang网联科技&#xff1a;连接未来&#xff0c;智能领航 公司简介 APang网联科技成立于 [2005年]&#xff0c;总部位于 [广东深圳]&#xff0c;是一家集网络技术研发、系统集成、项目实施与运维服务为一体的高新技术企业。我们致力于为客户提供全方位、定制化的网络部署解决…...

制作Unoconv项目的Docker镜像

制作Unoconv项目的Docker镜像 1 介绍 1.1 Unoconv 在Linux下将Office转换为pdf的很多包仅支持Windows&#xff0c;Unoconv是一个用LibreOffice转化文档的项目&#xff0c;已经归档&#xff08;2025-3-31&#xff09;。迁移后的新版本是unoserver&#xff0c;unoserver不太好…...

神经网络--拓扑排序+思维

1.c<0的点赋0&#xff0c;不然会影响后面的入度 2.最后输出层是出度为0的&#xff0c;且题干要求输出c大于0的 3.有q0的情况&#xff0c;所以输的事后就会有答案 https://www.luogu.com.cn/problem/P1038 #include<bits/stdc.h> #include<string> using nam…...

更强的视觉 AI!更智能的多模态助手!Qwen2.5-VL-32B-Instruct-AWQ 来袭

Qwen2.5-VL-32B-Instruct 是阿里巴巴通义千问团队于 2025 年 3 月 24 日开源的多模态大模型&#xff0c;基于 Apache 2.0 协议发布。该模型在 Qwen2.5-VL 系列的基础上&#xff0c;通过强化学习技术优化&#xff0c;以 32B 参数规模实现了多模态能力的突破。 核心特性升级&…...

逻辑过期怎么设计

设计“逻辑过期”通常用于缓存、令牌管理、数据有效性验证等场景&#xff0c;其核心是通过业务逻辑判断数据是否过期&#xff08;而非单纯依赖物理时间&#xff09;。以下是设计逻辑过期的关键思路和实现方案&#xff1a; 1. 核心思想 物理过期&#xff1a;基于固定的时间&…...

EMIF详解

一、EMIF的基本定义 EMIF&#xff08;External Memory Interface&#xff0c;外部存储器接口&#xff09; 是嵌入式处理器&#xff08;如DSP、FPGA、SoC&#xff09;用于连接外部存储器的专用硬件接口模块&#xff0c;负责管理处理器与存储器之间的地址/数据总线、控制信号及时…...

Kubernetes》》K8S》》Pod调度机制

nodeName 、nodeSelector nodeName 是强绑定&#xff0c;nodeSelector是弱绑定 强绑定&#xff0c;如果Node失效时&#xff0c;则会导致Pod也无法调度 apiVersion: v1 kind: Pod metadata:name: example-pod spec:# nodeName Pod应该被调度到哪个具体的节点上 强绑定nodeNam…...