Java进阶-反射

news2024/10/7 20:27:54

来学习一下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、private
                System.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转换为包装类型Integer
        if(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) {
        // 获取动态类Book
        Class 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) {
                        // 通过执行带两个参数的构造方法实例化book1
                        book1 = (Book) con.newInstance("Java 教程", 10);
                    } else if (i == 2) {
                        // 通过执行默认构造方法实例化book1
                        book1 = (Book) con.newInstance();
                    } else {
                        // 通过执行可变数量参数的构造方法实例化book1
                        Object[] 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.String
 int
该构造方法可能拋出的异常类型为:
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){
        // 获取动态类Book1
        Book1 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.String
 int
方法的返回值类型为: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();
        // 获取动态类Book2
        Class 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));
                    // 判断成员类型是否为int
                    if(fieldType.equals(int.class)) {
                        System.out.println("利用setInt()方法修改成员的值");
                        field.setInt(book, 100);
                    } else if(fieldType.equals(float.class)) {
                        // 判断成员变量类型是否为float
                        System.out.println("利用setFloat()方法修改成员的值");
                        field.setFloat(book, 29.815f);
                    } else if(fieldType.equals(boolean.class)) {
                        // 判断成员变量是否为boolean
                        System.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
=============================

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

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

相关文章

UDP数据报套接字编程入门

目录 1.TCP和UDP的特点及区别 1.1TCP的特点 1.2UDP的特点 1.3区别 2.UDP Socket的api的介绍 2.1DatagramSocket API 2.2DatagramPacket API 3.回显客户端与服务器 3.1回显服务器 3.1.1UdpEchoServer类的创建 3.1.2服务器的运行方法start() 3.1.3main部分 3.1.4.完整…

LeetCode #104 二叉树的最大深度

104. 二叉树的最大深度 题目 二叉树的 最大深度 是指从根节点到最远叶子节点的最长路径上的节点数。 示例 1&#xff1a; 输入&#xff1a;root [3,9,20,null,null,15,7] 输出&#xff1a;3 示例 2&#xff1a; 输入&#xff1a;root [1,null,2] 输出&#xff1a;2 分析 …

CMake、OpenCV 和单元测试

我写了很多关于 CMake 的文章&#xff0c;如果你感兴趣&#xff0c;可以点击以下链接阅读&#xff1a; CMake VS MakeCMake&#xff1a;在构建世界掀起风暴现代 CMake 使用技巧CMake 交叉编译CMake 生成器已开启 我们将继续对 CMake 的探索&#xff0c;这篇文章技术性高&…

云商大宗商品使用的是什么系统,有什么功能

云商大宗商品使用的系统主要包括大宗商品贸易系统、大宗商品仓储管理系统。 大宗商品贸易系统则是一种基于互联网技术的交易平台&#xff0c;旨在为买卖双方提供高效、安全、透明的交易环境。该系统具备商品管理、交易管理、资金管理、数据分析和风险管理等功能模块&#xff0…

2024年四川媒体新闻发布渠道,媒体邀约资源表

传媒如春雨&#xff0c;润物细无声&#xff0c;大家好&#xff0c;我是51媒体网胡老师。 四川有哪些媒体新闻发布渠道&#xff0c;媒体邀约资源表&#xff1f; 2024年四川媒体新闻发布渠道&#xff0c;媒体邀约资源表 四川本地媒体&#xff1a;如四川日报、华西都市报、成都商…

2024年最好的 5 款免费的数据恢复软件

数据意外损坏或丢失&#xff1f;别担心&#xff0c;今天我为大家带来了实用的免费硬盘数据恢复软件&#xff01; 在数字化时代&#xff0c;数据的重要性不言而喻。但是&#xff0c;由于种种原因&#xff0c;数据意外损坏或丢失的情况时有发生。此时&#xff0c;一款实用的免费…

SpringBoot 自定义映射规则resultMap association一对一

介绍 例&#xff1a;学生表&#xff0c;班级表&#xff0c;希望在查询学生的时候一起返回该学生的班级&#xff0c;而一个实体类封装的是一个表&#xff0c;如需要多表查询就需要自定义映射。 表结构 班级表 学生表 SQL语句 SELECT a.id,a.name,a.classes,b.id classes…

JS(JavaScript)中如何实现,复选框checkbox多选功能

起始界面&#xff1a; 代码元素&#xff1a; <p><input type"checkbox" id"checkedAll"> 全选按钮</p><p><input type"checkbox" class"cl"> 选项1</p><p><input type"checkbox&qu…

张驰咨询:为什么每个应届生都应该参加六西格玛培训?

应届生参加六西格玛培训的现象逐渐成为了一个新的趋势&#xff0c;这背后的原因不仅仅是市场对于品质管理人才的渴求&#xff0c;也源于应届生自身发展的需求。本文张驰咨询将从应届生的视角探讨参加六西格玛培训的动机&#xff0c;以及这种培训如何为他们的职业生涯铺路。 为…

认识通讯协议——TCP/IP、UDP协议的区别,HTTP通讯协议的理解

目录 引出认识通讯协议1、TCP/IP协议&#xff0c;UDP协议的区别2、HTTP通讯协议的讲解 Redis冲冲冲——缓存三兄弟&#xff1a;缓存击穿、穿透、雪崩缓存击穿缓存穿透缓存雪崩 总结 引出 认识通讯协议——TCP/IP、UDP协议的区别&#xff0c;HTTP通讯协议的理解 认识通讯协议 …

做活动和会议直播,为什么要多个媒体平台同步直播?

传媒如春雨&#xff0c;润物细无声&#xff0c;大家好&#xff0c;我是51媒体网胡老师。 多个媒体平台同步直播活动和会议的原因主要有以下几点&#xff1a; 扩大观众覆盖面&#xff1a;不同的媒体平台拥有各自独特的用户群体&#xff0c;通过在多个媒体平台同步直播&#xff…

Unity(第二十一部)动画的基础了解(感觉不了解其实也行)

1、动画组件老的是Animations 动画视频Play Automatically 是否自动播放Animate Physics 驱动方式&#xff0c;勾选后是物理驱动Culling Type 剔除方式 默认总是动画化就会一直执行下去&#xff0c;第二个是基于渲染播放&#xff08;离开镜头后不执行&#xff09;&#xff0c; …

如何解决 C/C++ 编译器优化导致的编译BUG(程序崩溃)支援VC++/CLANG/GCC

本文仅适用于&#xff0c;有愿意、爱捣鼓的童靴。 因编译器优化导致编译BUG&#xff0c;即DEBUG下面无故障稳定工作&#xff0c;但RELESE下程序会在特定函数位置上崩溃。 这要求 C/C 开发人员拥有最基本的素质&#xff0c;需要能够承受&#xff0c;逐行审视编译器输出的目标平…

yolov9,使用自定义的数据训练推理

[源码 &#x1f40b;]( GitHub - WongKinYiu/yolov9: Implementation of paper - YOLOv9: Learning What You Want to Learn Using Programmable Gradient Information) [论文 &#x1f4d8;](arxiv.org/pdf/2402.13616.pdf) 论文摘要&#xff1a;本文介绍了一种新的目标检测…

【 JS 进阶 】正则表达式

“生命是一幅抽象画&#xff0c;每一笔都是独特的经历。在色彩的交织中&#xff0c;用坚定的画笔勾勒出自己的轨迹&#xff0c;让每一幅画作都成为奋斗的印记。” - 亚历山大斯密斯 正则表达式 正则表达式&#xff08;Regular Expression&#xff09;是一种字符串匹配的模式&a…

二、TensorFlow结构分析(2)

目录 1、会话 1.1 __init__(target,graphNone,configNone) 1.2 会话的run() 1.3 feed操作 TF数据流图图与TensorBoard会话张量变量OP高级API 1、会话 1.1 __init__(target,graphNone,configNone) def session_demo():# 会话的演示# Tensorflow实现加法运算a_t tf.constan…

LNMP 架构

搭建 LNMP 架构需要安装 nginx mysql php 软件 linux nginx mysql php结合 在一台主机上搭建LNMP架构 一、编译安装 nginx 安装依赖包 yum -y install pcre-devel zlib-devel gcc gcc-c make 创建nginx程序用户 &#xff08;Nginx 服务程序默认以 nobody 身份运…

基于java Springboot实现课程评分系统设计和实现

基于java Springboot实现课程评分系统设计和实现 博主介绍&#xff1a;多年java开发经验&#xff0c;专注Java开发、定制、远程、文档编写指导等,csdn特邀作者、专注于Java技术领域 作者主页 央顺技术团队 Java毕设项目精品实战案例《1000套》 欢迎点赞 收藏 ⭐留言 文末获取源…

MySQL(基础篇)——事务

一.事务简介 事务是一组操作的集合&#xff0c;他是一个不可分割的单位&#xff0c;事务会把所有的操作作色一个整体一起向系统提交或撤销操作请求&#xff0c;即这些操作要么同时成功&#xff0c;要么同时失败。 默认MySQL的事务是自动提交的&#xff0c;也就是说&#xff0c…

QML中动态增加表格数据

1.QML中的表格实现 import QtQuick 2.15 import QtQuick.Window 2.15import QtQuick.Controls 2.0 import Qt.labs.qmlmodels 1.0 import QtQuick.Layouts 1.15Window {width: 640height: 480visible: truetitle: qsTr("Hello World")TableModel{id:table_modelTabl…