java中的反射

news2024/11/20 7:04:17

反射

类加载的过程

	当程序主动使用某个类时,如果该类还未被加载到内存中,则JVM会通过加载、连接、初始化3个步骤来对该类进行初始化。如果没有意外,JVM将会连续完成3个步骤,所以有时也把这个3个步骤统称为类加载或类初始化。

rfjhmhy54fhysjuhye

加载
加载指的是将类的class文件读入到内存,并为之创建一个java.lang.Class对象(字节码对象),也就是说,当程序中使用任何类时,系统都会为之建立一个java.lang.Class对象(一个类只可能有一个字节码对象)。
现在 : 对象.getClass() == 类名.class --> 前面的对象是否属于后面的类型
    
以前的写法: 对象 instanceof

类的加载由类加载器(ClassLoader)完成,类加载器通常由JVM提供,这些类加载器也是前面所有程序运行的基础,JVM提供的这些类加载器通常被称为系统类加载器。除此之外,开发者可以通过继承ClassLoader基类(类加载器的基类)来创建自己的类加载器[自定义类加载器]。

通过使用不同的类加载器,可以从不同来源加载类的二进制数据(字节码文件),通常有如下几种来源。

  1. 从本地文件系统加载class文件,这是前面绝大部分示例程序的类加载方式。

  2. 从JAR包加载class文件,这种方式也是很常见的,JDBC编程时用到的数据库驱动类就放在JAR文件中,JVM可以从JAR文件中直接加载该class文件。

  3. 通过网络加载class文件。
    把一个Java源文件动态编译,并执行加载。

    类加载器通常无须等到“首次使用”该类时才加载该类,Java虚拟机规范允许系统预先加载某些类。

链接
当类被加载之后,系统为之生成一个对应的Class对象,接着将会进入连接阶段,连接阶段负责把类的二进制数据(字节码对象)合并到JRE中。类连接又可分为如下3个阶段。

1)验证:验证阶段用于检验被加载的类是否有正确的内部结构,并和其他类协调一致。Java是相对C++语言是安全的语言,例如Java有C++不具有的数组越界的检查。这本身就是对自身安全的一种保护。验证阶段是Java非常重要的一个阶段,它会直接的保证应用是否会被恶意入侵的一道重要的防线,越是严谨的验证机制越安全。验证的目的在于确保Class文件的字节流中包含信息符合当前虚拟机要求,不会危害虚拟机自身安全。其主要包括四种验证,文件格式验证,元数据验证,字节码验证,符号引用验证。

四种验证做进一步说明:

文件格式验证:主要验证字节文件是否符合Class文件格式规范,并且能被当前的虚拟机加载处理。例如:主,次版本号是否在当前虚拟机处理的范围之内。常量池中是否有不被支持的常量类型。指向常量的中的索引值是否存在不存在的常量或不符合类型的常量。

元数据验证:对字节码描述的信息进行语义的分析,分析是否符合java的语言语法的规范。

字节码验证:最重要的验证环节,分析数据流和控制,确定语义是合法的,符合逻辑的。主要的针对元数据验证后对方法体的验证。保证类方法在运行时不会有危害出现。

符号引用验证:主要是针对符号引用转换为直接引用的时候,是会延伸到第三解析阶段,主要去确定访问类型等涉及到引用的情况,主要是要保证引用一定会被访问到,不会出现类等无法访问的问题。

2)准备:类准备阶段负责为类的静态变量分配内存,并设置默认初始值(系统默认值)。

**3)解析:**将类的二进制数据[字节码对象]中的符号引用替换成直接引用。说明一下:符号引用:符号引用是以一组符号来描述所引用的目标,符号可以是任何的字面形式的字面量,只要不会出现冲突能够定位到就行。布局和内存无关。直接引用:是指向目标的指针,偏移量或者能够直接定位的句柄。该引用是和内存中的布局有关的,并且一定加载进来的。

初始化
初始化是为类的静态变量赋予正确的初始值(程序员给静态成员变量赋的值),准备阶段和初始化阶段看似有点矛盾,其实是不矛盾的,如果类中有语句:private static int a = 10,它的执行过程是这样的,首先字节码文件被加载到内存后,先进行链接的验证这一步骤,验证通过后准备阶段,给a分配内存,因为变量a是static的,所以此时a等于int类型的默认初始值0,即a=0,然后到解析,到初始化这一步骤时,才把a的真正的值10赋给a,此时a=10。
总结:
	加载: 生成类的字节码对象
    链接:
		验证: 校验字节码对象中的成员是否符合Java类规范
        准备: 加载类中静态成员并赋予系统默认值
        解析: 把类中的符号引用替换成直接引用
    初始化: 把类中静态成员的默认值替换成真实值;

fdw3hjyt6sd3edhn

类何时加载

  1. 创建类的实例,也就是new一个对象
  2. 访问某个类或接口的静态变量,或者对该静态变量赋值
  3. 调用类的静态方法
  4. 反射(Class.forName(“全类名”))
  5. 初始化一个类的子类(会首先初始化子类的父类)
  6. JVM启动时标明的启动类,即文件名和类名相同的那个类

类何时被加载: 类第一次被使用的时候加载

类加载器

类加载器负责加载所有的类,其为所有被载入内存中的类生成一个java.lang.Class实例对象。一旦一个类被加载如JVM中,同一个类就不会被再次载入了。
  1. 根类加载器(bootstrap classloader):它用来加载 Java 的核心类,是用原生代码来实现的,并不继承自 java.lang.ClassLoader(负责加载$JAVA_HOME中jre/lib/rt.jar里所有的class,由C++实现,不是ClassLoader子类)。由于引导类加载器涉及到虚拟机本地实现细节,开发者无法直接获取到启动类加载器的引用,所以不允许直接通过引用进行操作。
  2. 扩展类加载器(extensions classloader):它负责加载JRE的扩展目录,lib/ext或者由java.ext.dirs系统属性指定的目录中的JAR包的类。由Java语言实现,父类加载器为null。
  3. 系统类加载器(system class loader):被称为系统(也称为应用)类加载器,它负责在JVM启动时加载来自Java命令的-classpath选项、java.class.path系统属性,或者CLASSPATH换将变量所指定的JAR包和类路径。程序可以通过ClassLoader的静态方法getSystemClassLoader()来获取系统类加载器。如果没有特别指定,则用户自定义的类加载器都以此类加载器作为父加载器。
  4. 自定义类加载器(custom class loader): 我要指定一些类由某个类加载器加载 那么就可以自定义类记载器

类加载器加载Class的8个步骤[了解]

1. 检测此Class是否载入过,即在缓冲区中是否有此Class,如果有直接进入第8步,否则进入第2步。
2. 如果没有父类加载器,则要么Parent是根类加载器,要么本身就是根类加载器,则跳到第4步,如果父类加载器存在,则进入第3步。
3. 请求使用父类加载器去载入目标类,如果载入成功则跳至第8步,否则接着执行第5步。
4. 请求使用根类加载器去载入目标类,如果载入成功则跳至第8步,否则跳至第7步。
5. 当前类加载器尝试寻找Class文件,如果找到则执行第6步,如果找不到则执行第7步。
6. 从文件中载入Class,成功后跳至第8步。
7. 抛出ClassNotFountException异常。
8. 返回对应的java.lang.Class对象。

类加载机制-双亲委派模型

fhjy4rfrhyjugtredfrgty

类加载器使用场景(重要)

类加载器的功能: 快速获取当前类所在模块src文件夹根目录下的文件 [开辟一个相对路径的起点]
    //IO知识的相对路径起点 : 项目的根
    //类加载器的相对路径起点 : 当前代码所在模块的src根目录
    
ClassLoader: 类加载器的类(类加载器的基类)   
    static ClassLoader getSystemClassLoader() : 获取到系统类加载器对象
    InputStream getResourceAsStream(String fileName): 快速的获取传入文件路径指向的文件
    	String fileName: 文件路径 --> 相对路径写: 相对路径的起点是src文件夹
            
	static InputStream getSystemResourceAsStream(String name):直接获取输入流对象 -> 推荐方法  
//示例1
    public static void main(String[] args) {
        //目前没有自定义类加载器 -> 最底层的类加载器是 : 系统类加载器
        ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
        System.out.println("systemClassLoader = " + systemClassLoader);
        //系统类加载器 找其"父类"加载器 [逻辑继承] -> 拓展类加载器
        ClassLoader extraClassLoader = systemClassLoader.getParent();
        System.out.println("extraClassLoader = " + extraClassLoader);
        //拓展类加载器 找其"父类"加载器 [逻辑继承] -> 根类加载器
        ClassLoader rootClassLoader = extraClassLoader.getParent();
        System.out.println("rootClassLoader = " + rootClassLoader);
    }
//示例2
	login.propertie :
        username=admin
        password=123456
            
    public static void main(String[] args) throws IOException {
        //IO : 相对路径起点 项目根目录
        //BufferedReader br = new BufferedReader(
        // new FileReader("Test\\src\\com\qh\classloader\login.propertie"));
        //类加载器 : 相对路径的起点 : 当前模块的src根目录
//        ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
//        InputStream is = systemClassLoader
//                .getResourceAsStream("com\qh\classloader\login.propertie");
        InputStream is = ClassLoader.
                getSystemResourceAsStream("com\\qh\\classloader\\login.properties");
        Properties properties = new Properties();
        properties.load(is);
        String username = properties.getProperty("username");
        String password = properties.getProperty("password");
        Scanner scanner = new Scanner(System.in);
        System.out.println("请你输入您的账号 : ");
        String uName = scanner.nextLine();
        System.out.println("请您输入您的密码 : ");
        String pwd = scanner.nextLine();
        if (username.equals(uName) && password.equals(pwd)){
            System.out.println("登录成功!");
        }else{
            System.out.println("登录失败!");
        }
    }

反射

反射 : 一种知识体系 [此知识体系在获取类中的成员并使用[构造方法,成员变量/常量,成员方法,注解...]]
    
反射是未来框架的底层源码使用的知识体系;  //框架 : 帮助程序员快捷开发的代码

思想层面 : 
以前你是普通工程师 : 直面需求 
未来你是框架工程师 : 直面解决需求的人 
    
代码层面 : //编写代码的手法
	"正射" : 学生对象调用学习方法(几个小时) -> student.study(8);
	反射 : 学习方法对象启动传入需要学习的学生对象和学习的时间 -> study方法对象.invoke(student,8);

学习反射的目的 : 是为了未来能看懂 框架 的底层源码;

反射使用的步骤

1. 获取类的字节码对象 [因为类的字节码对象中封装着类的成员]
2. 通过字节码对象获取类中的成员 [构造方法(Constructor),成员变量(Field),成员方法(Method)]   
3. 类中成员对象自启动 [构造方法-> 创建对象,成员变量 -> 获取值/赋值.成员方法 -> 启动方法]    

获取类的字节码对象[反射起手式]

1. 对象.getClass() [getClass()来自于Object]
2. 类名.class [class属性 : 每个类型都有的属性(包含数组,包含基本数据类型)] //int[].class int数组的字节码对象, int.class 整型的字节码对象....
3. Class.forName("类的全类名") :   类的全类名-> 包名.类名  
//示例
    public static void main(String[] args) throws ClassNotFoundException {
        //获取Student类的字节码对象
        //1. 对象.getClass()
        Student1 student1 = new Student1();
        Class aClass1 = student1.getClass();
        //2. 类名.class
        Class aClass2 = Student1.class;
        //3. Class.forName("全类名")
        Class aClass3 = Class.forName("com.qh.reflect.Student1");
        System.out.println("aClass1 = " + aClass1);
        System.out.println("aClass2 = " + aClass2);
        System.out.println("aClass3 = " + aClass3);
        //一个类的字节码对象只可能有一个
        System.out.println(aClass1 == aClass1);
        System.out.println(aClass2 == aClass2);
        System.out.println(aClass3 == aClass3);
    }

获取类中成员

获取类中的构造方法对象
获取字节码对象中封装的构造方法对象 : 
	//只能获取public修饰的构造方法对象 -> 可以看到父类public修饰的构造方法
	Constructor<?>[] getConstructors() : 获取类中所有的构造方法对象
    Constructor<T> getConstructor(Class<?>... parameterTypes) : 获取类中指定的构造方法对象  
    
    //任何权限修饰符的构造方法对象都能获取 -> 弊端 : 不能获取父类的构造方法
    Constructor<?>[] getDeclaredConstructors()  
    Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes) 
    Class<?>... parameterTypes : 方法形参类型的字节码对象
获取类中的成员变量对象
获取字节码对象中封装的成员变量对象 :
	Field[] getFields()  
    Field getField(String name)  
        
    //推荐
    Field[] getDeclaredFields()  
    //String name : 要获取的成员变量的变量名    
    Field getDeclaredField(String name)      
获取类中的成员变量对象
获取字节码对象中封装的成员变量对象 :
	Field[] getFields()  
    Field getField(String name)  
        
    //推荐
    Field[] getDeclaredFields()  
    //String name : 要获取的成员变量的变量名    
    Field getDeclaredField(String name)      

获取类中的成员方法对象

获取字节码对象中封装的成员方法对象 :
	Method[] getMethods()  
    Method getMethod(String name)  
        
    //推荐
    Method[] getDeclaredFields()   
    //String name : 要获取的成员变量的变量名    
  	Method getDeclaredMethod(String name,<?>... parameterTypes)

使用类中成员

如果该成员是没有访问权限的,虽然Declared系列方法能够获取此成员对象,但是真正使用时需要开启暴力反射开关!

void setAccessible(boolean flag) : 开启暴力反射开关 //只需要在使用没有权限的成员之前,开启暴力反射开关即可

使用类中构造方法对象[创建对象]
 T newInstance(Object... initargs)  : 使用构造方法对象创建对象
     返回值T : 得到的对象
     Object... initargs :  此构造方法对象启动需要的实际参数 [形参和实参匹配]   

 //在Class类中有一个快捷创建此类对象的方法 [启动的是类中的无参构造(使用前提是: 类中必须有无参构造)]
        //Class 类中的方法 : T newInstance()
        Student student = clazz.newInstance();
        System.out.println("student = " + student);         
使用类中成员变量对象[设置值和获取值]
获取值的方法 :
	Object get(Object obj)  
        返回值 Object : 拿到的成员变量的值
        形参 Object obj : 你要获取的是哪个对象的该属性值    
        
设置值的方法 :
	void set(Object obj, Object value) 
       	形参 Object obj : 你要设置的是哪个对象的该属性值  
        形参 Object value : 你要设置的值    
//示例1:构造方法
    public class Student1 {
        private String name;
        int age;
        public String address;
        protected String sex;
        public Student1() {
            System.out.println("无参构造启动了");
        }
        private Student1(String name) {
            System.out.println("private-"+name);
        }
        Student1(String name, int age){
            System.out.println("默认-"+name+"-"+age);
        }
        public Student1(String name, int age, String address) {
            System.out.println("public-"+name+"-"+age+"-"+address);
        }
        protected Student1(int age, String sex){
            System.out.println("protected-"+age+"-"+sex);
        }
    }
    public static void main(String[] args) throws InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
        Class<Student1> student1Class = Student1.class;
        // 返回一个包含 Constructor对象的数组,反映由该Class对象表示的类的所有 [公共] 构造函数
        Constructor<?>[] constructors = student1Class.getConstructors();
        for (Constructor constructor : constructors) {
            System.out.println("constructor = " + constructor);
        }
        System.out.println("-------------");
        // 返回由该 Class对象表示的类声明的 [所有] 构造函数的 Constructor对象的数组
        Constructor[] declaredConstructors = student1Class.getDeclaredConstructors();
        for (Constructor declaredConstructor : declaredConstructors) {
            System.out.println("declaredConstructor = " + declaredConstructor);
        }
        System.out.println("-------------");
        // 返回一个 Constructor对象,该对象反映由该Class对象表示的类的指定 [公共] 构造函数
        // 参数:要获取的构造方法的参数的个数及数据类型对应的字节码文件对象
        Constructor<Student1> declaredConstructor1 = student1Class.getDeclaredConstructor();
        System.out.println("declaredConstructor1 = " + declaredConstructor1);
        Constructor<Student1> declaredConstructor2 = student1Class.getDeclaredConstructor(String.class);
        System.out.println("declaredConstructor2 = " + declaredConstructor2);
        Constructor<Student1> declaredConstructor3 = student1Class.getDeclaredConstructor(String.class,int.class);
        System.out.println("declaredConstructor3 = " + declaredConstructor3);
        Constructor<Student1> declaredConstructor4 = student1Class.getDeclaredConstructor(String.class,int.class,String.class);
        System.out.println("declaredConstructor4 = " + declaredConstructor4);
        Constructor<Student1> declaredConstructor5 = student1Class.getDeclaredConstructor(int.class,String.class);
        System.out.println("declaredConstructor5 = " + declaredConstructor5);
        System.out.println("-------------");//在Class类中有一个快捷创建此类对象的方法 [启动的是类中的无参构造(使用前提是: 类中必须有无参构造)]
        //Class 类中的方法 : T newInstance()
        Student1 student10 = student1Class.newInstance();
        System.out.println("student0 = " + student10);
        //根据构造方法对象获取此类的对象
        Student1 student0 = declaredConstructor1.newInstance();
        System.out.println("student0 = " + student0);
        declaredConstructor2.setAccessible(true);//开启暴力反射开关
        Student1 student2 = declaredConstructor2.newInstance("张三");//没有访问权限,不能直接访问private
        System.out.println("student2 = " + student2);
        Student1 student3 = declaredConstructor3.newInstance("李四", 23);
        System.out.println("student3 = " + student3);
        Student1 student4 = declaredConstructor4.newInstance("王五", 24, "上海");
        System.out.println("student4 = " + student4);
        Student1 student5 = declaredConstructor5.newInstance( 24, "男");
        System.out.println("student5 = " + student5);
        System.out.println("-------------");
    }
//示例2:成员变量
    public class Student2 {
        private String name;
        int age;
        public String address;
        protected String sex;
    }
	public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
        Student2 Student2 = new Student2();
        Class student2Class = Student2.getClass();
        返回一个包含Field对象的数组,Field对象反映由该Class对象表示的类或接口的所有可访问的 [公共] 的成员变量
        Field[] fields = student2Class.getFields();
        for (Field field : fields) {
            System.out.println("field = " + field);
        }
        System.out.println("----------------");
        //返回一个包含Field对象的数组,Field对象反映由该Class对象表示的类或接口的 [所有] 成员变量
        Field[] declaredFields = student2Class.getDeclaredFields();
        for (Field declaredField : declaredFields) {
            System.out.println("declaredField = " + declaredField);
        }
        System.out.println("----------------");
        //获取单个类中成员变量对象
        Field name = student2Class.getDeclaredField("name");
        name.setAccessible(true);
        Field age = student2Class.getDeclaredField("age");
        Field address = student2Class.getDeclaredField("address");
        Field sex = student2Class.getDeclaredField("sex");
        System.out.println("name = " + name);
        System.out.println("age = " + age);
        System.out.println("address = " + address);
        System.out.println("sex = " + sex);
        System.out.println("----------------");
        //赋值
        name.setAccessible(true);//开启暴力反射开关
        name.set(Student2,"张三");
        age.set(Student2,23);
        address.set(Student2,"上海");
        sex.set(Student2,"男");
        //获取值
        Object nameValue = name.get(Student2);
        Object ageValue = age.get(Student2);
        Object addressValue = address.get(Student2);
        Object sexValue = sex.get(Student2);
        System.out.println("nameValue = " + nameValue);
        System.out.println("ageValue = " + ageValue);
        System.out.println("addressValue = " + addressValue);
        System.out.println("sexValue = " + sexValue);
    }
//示例3:成员方法
    public class Student3 {
        public void S1(){
            System.out.println("public");
        }
        protected void S2(String name){
            System.out.println("protected-"+name);
        }
        String S3(){
            System.out.println("默认");
            return "默认";
        }
        private void S4(int age){
            System.out.println("private-"+age);
        }
    }
    public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        Student3 student3 = new Student3();
        Class<? extends Student3> student3Class = student3.getClass();
        //返回一个包含方法对象的数组,方法对象反映由该Class对象表示的类或接口的所有 公共方法
        //包括由类或接口声明的对象以及从超类和超级接口继承的类
        Method[] methods = student3Class.getMethods();
        for (Method method : methods) {
            System.out.println("method = " + method);
        }
        System.out.println("-----------------------");
        //返回一个包含方法对象的数组,方法对象反映由该Class对象表示的类或接口的所有声明方法
        //包括:public\protected\default(package)访问和私有方法,但不包括继承方法
        Method[] declaredMethods = student3Class.getDeclaredMethods();
        for (Method declaredMethod : declaredMethods) {
            System.out.println("declaredMethod = " + declaredMethod);
        }
        System.out.println("-----------------------");
        //单独获取成员方法对象
        Method s1 = student3Class.getDeclaredMethod("S1");
        Method s2 = student3Class.getDeclaredMethod("S2",String.class);
        Method s3 = student3Class.getDeclaredMethod("S3");
        Method s4 = student3Class.getDeclaredMethod("S4",int.class);
        System.out.println("s1 = " + s1);
        System.out.println("s2 = " + s2);
        System.out.println("s3 = " + s3);
        System.out.println("s4 = " + s4);
        System.out.println("-----------------------");
        System.out.println("s1.invoke(student3) = " + s1.invoke(student3));
        System.out.println("s2.invoke(student3,\"张三\") = " + s2.invoke(student3, "张三"));
        System.out.println("s3.invoke(student3) = " + s3.invoke(student3));
        s4.setAccessible(true);//开启暴力反射开关
        System.out.println("s4.invoke(student3,23) = " + s4.invoke(student3, 23));
    }
//示例4:
	info. :
		className=com.qh.reflect.Test
        methodName=show
    public class Test {
        public void show(){
            System.out.println("show()方法执行了");
        }
        public void method(){
            System.out.println("method()方法执行了");
        }
	}
	public class TestDemo {
    public static void main(String[] args) throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
        //获取配置文件中的信息
        InputStream systemResourceAsStream = ClassLoader
                .getSystemResourceAsStream("com\\qh\\reflect\\info.properties");
        //一键加载到属性集里
        Properties properties = new Properties();
        properties.load(systemResourceAsStream);
        //获取信息
        String className = properties.getProperty("className");
        String methodName = properties.getProperty("methodName");
        systemResourceAsStream.close();
        //反射代码
        //获取类的字节码对象
        Class classForName = Class.forName(className);
        //创建此类对象
        Object name = classForName.newInstance();
        //获取类中成员方法对象
        Method declaredMethod = classForName.getDeclaredMethod(methodName);
        //启动方法
        declaredMethod.invoke(name);
    }
}

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

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

相关文章

MySQL面试常问问题(索引) —— 赶快收藏

目录 1.能简单说一下索引的分类吗&#xff1f; 2.为什么使用索引会加快查询&#xff1f; 3.创建索引有哪些注意点&#xff1f; 4.索引哪些情况下会失效呢&#xff1f; 5.索引不适合哪些场景呢&#xff1f; 6.索引是不是建的越多越好呢&#xff1f; 7.MySQL索引用的什么数…

HackTheBox Soccer 通过WebSockets进行SQL注入,Doas与Dstat插件提权

靶机网址&#xff1a; https://app.hackthebox.com/machines/Precious枚举 使用nmap枚举靶机 nmap -sC -sV 10.10.11.194机子开放了22&#xff0c;80和9091端口&#xff0c;我们本地dns解析这个域名 echo "10.10.11.194 soccer.htb" >> /etc/hosts然后fuzz…

SpringBoot启动时无法加载自定义配置文件(根据环境不同,本地和生产)

问题背景 springboot启动的时候总是报找不到ftp_upload.properties. 估计同学该诧异了&#xff0c;明明就是在项目下的config下&#xff0c;为啥找不到呢&#xff1f;我们都知道springboot的配置文件启动加载顺序是&#xff1a; 第一&#xff1a; ./config/(项目根目录下的…

【文献阅读笔记】利用松弛方法解决非凸问题

文章目录如何判断凸函数常见的凸函数复合函数判断是否凸函数对于约束问题使用泰勒公式进行松弛参考文献如何判断凸函数 当满足下面的公式时候可以判断目标函数为凸函数 f(ξx(1−ξ)y)<ξf(x)(1−ξ)f(y)f(\xi x(1-\xi)y)<\xi f(x)(1-\xi)f(y) f(ξx(1−ξ)y)<ξf(x)…

eclipse整合tomcat+maven

eclipse整合tomcatmaven 前提 本地安装好 tomcat 本地安装好 maven 本地选择一个目录作为 eclipse 工作空间 , 即 workspace 我本地 tomcat 版本是 8.5 , maven 版本是 3.6.1 整合tomcat windows —> preferences --> 搜索 Runtime 选择本地对应的 tomcat 版本 (我…

VXLAN技术是什么,谈何打破与大厂项目的技术壁垒

随着IT环境的不断变化以及新技术的快速发展&#xff0c;新的客户需求下&#xff0c;新的隧道协议也随之被引入进来。从GRE到VXLAN、GENEVE&#xff0c;网络虚拟化技术得到迅猛发展。 尤其是在大数据背景下&#xff0c;海量数据的处理对网络中数据中心的虚拟化、数据迁移等问题提…

BitSail issue 持续更新中,快来挑战,赢取千元礼品!

背景介绍 近期&#xff0c;BitSail 社区发布了 Contributor 激励计划第一期&#xff0c;包含众多 issue&#xff0c;吸引了很多热衷开源的小伙伴的加入&#xff0c;详情可查看&#x1f449;https://mp.weixin.qq.com/s/GkGs-EqTV-szvzndMYrG1g Issue 介绍 为了扩展 BitSail …

全面edge浏览器体验优化

前言 使用Windows系统的朋友们肯定都多少会用到edge浏览器&#xff0c;但是你们都真的了解edge的实用功能吗&#xff0c;本文会介绍edge优秀好用的自带功能以及能极大程度提升使用体验的第三方插件&#xff0c;帮助你打造一个用着更加顺手方便的edge浏览器。 自带功能 1、re…

m基于GNN图神经网络的目标匹配分析matlab仿真

目录 1.算法描述 2.仿真效果预览 3.MATLAB核心程序 4.完整MATLAB 1.算法描述 在一些应用领域数据可以自然而然地表示成图结构&#xff0c;包括 蛋白质组学&#xff0c;图像分析&#xff0c;场景描述 &#xff0c;软件工程&#xff0c;和自然语言处理。最简单的图结构包括单…

车辆信息网站

开发工具(eclipse/idea/vscode等)&#xff1a; 数据库(sqlite/mysql/sqlserver等)&#xff1a; 功能模块(请用文字描述&#xff0c;至少200字)&#xff1a;

当谈论 React hook,我们究竟说的是什么?

这个标题很大&#xff0c;但是落点很小&#xff0c;只是我&#xff0c;一个开发者在学习和使用 hooks 中的一点感受和总结。 React hook 的由来 React hook 的由来&#xff0c;其实也可以看作是前端技术不断演进的结果。 在 world wide web 刚刚诞生的洪荒时代&#xff0c;还…

无人机自由飞行测试台 FFT GYRO 600

产品简介 无人机在研制过程中需要不断地进行飞行测试&#xff0c;而测试的过程不是万无一失的&#xff0c;飞行过程中发生任何错误都有可能会导致无人机的损毁或破坏&#xff0c;更严重地甚至会造成外界伤害。 基于此我们推出了无人机的三旋转自由度(3-DOF)飞行平台测试系统&…

标准I/O

1.标准I/O介绍 文件基础 概念&#xff1a; 一组相关数据的有序集合 文件类型&#xff1a; 常规文件 r 目录文件 d 字符设备文件 c 键盘&#xff0c;鼠标 块设备文件 b U盘&#xff0c;SD卡等 管道文件 p 套接字文件 s 符号链接文件 l &#xff08;类似于快捷方式&#xff09;…

【Lua】Lua基础语法

1 Lua 简介 Lua 是一个小巧的脚本语言&#xff0c;用标准C语言编写而成&#xff0c;由巴西里约热内卢天主教大学的 Roberto Ierusalimschy、Waldemar Celes 和 Luiz Henrique de Figueiredo 三人于 1993 年开发&#xff0c;设计目的是为了灵活嵌入应用程序&#xff0c;实现灵活…

基础IO——缓冲区

文章目录1. 缓冲区理解1.1 缓冲区在哪里1.2 刷新策略2. 标准输出和标准错误2.1 模拟perror1. 缓冲区理解 什么是缓冲区呢&#xff1f; 缓冲区的本质&#xff1a;就是一段内存 为什么要有缓冲区呢&#xff1f; 大家在日常生活中&#xff0c;如果我们想寄东西给朋友&#xff0c…

ELK集群部署---LogStash,Filebeat的部署

1. 环境规划: 主机名IP地址角色node1192.168.56.111 ElasticSearch(master) Zookeeper Kafka node2192.168.56.112 ElasticSearch(slave) Kibana Zookeeper Kafka node3192.168.56.113 ElasticSearch(slave) Zookeeper Kafka node4192.168.56.114 Logstash Filebeat 2. nod…

vue 实现类似甘特图大屏效果

最近在做大屏展示&#xff0c;其中一个需求是展示生产过程中投料情况&#xff0c;效果类似甘特图。 思路&#xff1a;1.先得到整个过程的开始时间startTime和结束时间endTime。计算出整个过长经历的时长。 2.计算横向坐标的开始时间start和结束时间end&#xff0c;坐标的开始时…

五分钟了解GRE是什么,四信GRE相关应用推荐

随着互联网新技术的发展以及智能化水平的提高&#xff0c;各企业对实时数据传输的需求也在不断提升&#xff0c;企业愈发重视数据中心的建设&#xff0c;各类虚拟网络技术相继被引入。今天&#xff0c;我们重点了解下云端“借道”鼻祖&#xff0c;善于“包装”的GRE&#xff0c…

新品上市|四信LTE Cat.1无线数传终端 推进中低速蜂窝典型应用

当前&#xff0c;物联网作为新型信息基础设施&#xff0c;已成为推动制造业、零售业、金融业、服务业等行业数字转型、智能升级、融合创新的重要支撑。《“十四五”信息通信行业发展规划》提出&#xff0c;要推进移动物联网全面发展&#xff0c;推动存量2G/3G物联网业务向NB-Io…

SSM医院病历

开发工具(eclipse/idea/vscode等)&#xff1a; 数据库(sqlite/mysql/sqlserver等)&#xff1a; 功能模块(请用文字描述&#xff0c;至少200字)&#xff1a;