Java笔记041-反射/类加载、通过反射获取类的结构信息、通过反射创建对象、通过反射访问类中的成员

news2024/11/24 13:04:17

反射


类加载

  • 基本说明

ClassLoad_

反射机制是Java实现动态语言的关键,也就是通过反射实现类动态加载。

  1. 静态加载:编译时加载相关的类,如果没有则报错,依赖性太强
  2. 动态加载:运行时加载需要的类,如果运行时不用该类,则不报错,降低了依赖性
  3. 举例说明
  • 类加载时机

  1. 当创建对象时(new) //静态加载
  2. 当子类被加载时,父类也加载//静态加载
  3. 调用类中的静态成员时//静态加载
  4. 通过反射//动态加载

Class.forName("com22.test.Cat")

package com22.reflection.ClassLoad_;

import java.lang.reflect.*;
import java.util.Scanner;

/**
 * @ClassName ClassLoad_
 * @Description TODO
 * @Author 甲柒
 * @Date 2023/9/12 8:46
 * @Version 1.0
 **/
public class ClassLoad_ {
    public static void main(String[] args) throws Exception {
        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入key");
        String key = scanner.next();
        switch (key) {
            case "1":
//                Dog dog = new Dog();//静态加载类,依赖性很强
//                dog.cry();
                break;
            case "2":
                //反射-》动态加载
                Class cls = Class.forName("Person");//加载Person类【动态加载】
                Object o = cls.newInstance();
                Method m = cls.getMethod("hi");
                m.invoke(o);
                System.out.println("ok");
                break;
            default:
                System.out.println("do nothing...");
        }
    }
}

//因为new Dog() 是静态加载,因此必须编写Dog
//Person类是动态加载,所以,没有编写Person类也不会报错,只有当动态加载该类时,才会报错
//class Dog {
//    public void cry() {
//        System.out.println("灰太狼~~~嗷呜~~~~~");
//    }
//}
//
//class Person {
//    public void hi() {
//        System.out.println("灰太狼:我一定会回来的~~~");
//    }
//}
  • 类加载过程图

  • 类加载各阶段完成任务 

  • 加载阶段

JVM在该阶段的主要目的是将字节码从不同的数据源(可能是class文件、也可能是jar包,甚至网络)转化为二进制字节流加载到内存中,并生成一个代表该类的java.lang.Class对象 

  • 连接阶段——验证

  1. 目的是为了确保Class文件的字节流中包含的信息符合当前虚拟机的要求,并且不会危害虚拟机自身的安全。
  2. 包括:文件格式验证(是否以魔数oxcafebabe开头)、源数据验证、字节码验证和符号引用验证【举例说明】
  3. 可以考虑使用 -Xverify:none参数来关闭大部分的类验证措施,缩短虚拟机类加载的时间。
  • 连接阶段——准备

  1. JVM会在该阶段对静态变量,分配内存并默认初始化(对应数据类型的默认初始值,如0、0L、null、false等)。这些变量所使用的内存都将在方法区中进行分配
  2. 举例说明:ClassLoad02.java
package com22.reflection.ClassLoad_;

/**
 * @ClassName ClassLoad02
 * @Description 说明一个类加载的链接阶段-准备
 * @Author 甲柒
 * @Date 2023/9/12 10:09
 * @Version 1.0
 **/
public class ClassLoad02 {
    public static void main(String[] args) {

    }
}

class A {
    //属性-成员变量-字段
    //分析类加载的链接阶段-准备 属性是如何处
    //1. n1 是实例属性, 不是静态变量,因此在准备阶段,是不会分配内存
    //2. n2 是静态变量,分配内存 n2 是默认初始化 0 ,而不是 20
    //3. n3 是 static final 是常量, 他和静态变量不一样, 因为一旦赋值就不变 n3 = 30
    public int n1 = 10;
    public static int n2 = 20;
    public static final int n3 = 30;
}
  • 连接阶段——解析

  1. 虚拟机将常量池内的符号引用替换为直接引用的过程
  2. 举例说明:
  • Initialization(初始化)

  1. 到初始化阶段,才真正开始执行类中定义的Java程序代码,此阶段是执行<clinit>()方法的过程。
  2. <clinit>()方法是由编译器按语句在源文件中出现的顺序,依次自动收集类中的所有静态变量的赋值动作和静态代码块中的语句,并进行合并。【ClassLoad03.java】
  3. 虚拟机会保证一个类的<clinit>()方法在多线程环境中去执行这个类的<clinit>()方法,其他线程都需要阻塞等待,直到活动线程执行<clinit>()方法完毕【debug源码】

 ClassLoad03.java

package com22.reflection.ClassLoad_;

/**
 * @ClassName ClassLoad03
 * @Description 演示类加载——初始化阶段
 * @Author 甲柒
 * @Date 2023/9/12 11:12
 * @Version 1.0
 **/
public class ClassLoad03 {
    public static void main(String[] args) throws ClassNotFoundException {
        //分析
        //1.加载B类,并生成B的class对象
        //2.连接 num = 0
        //3.初始化阶段
        //  依次自动收集类中的所有静态变量的赋值动作和静态代码块中的语句,并合并
        /*
            clinit(){
                System.out.println("B 的静态代码块被执行");
                //num = 300;
                num = 100;
            }
                合并num = 100;
        * */
//        B b = new B();
//        System.out.println(B.num);//100,如果直接使用类的静态属性,也会导致类的加载

        //在加载类的时候是有同步机制的,正因有同步机制,才能保证某个类在内存中只有一份class对象
        B b = new B();
    }
}

class B {
    static {
        System.out.println("B 的静态代码块被执行");
        num = 300;
    }

    static int num = 100;

    public B() {//构造器
        System.out.println("B() 构造器被执行");
    }
}

运行结果


通过反射获取类的结构信息

  • 第一组:java.lang.Class类

getName获取全类名
getSimpleName获取简单类名
getFields获取所有public修饰的属性,包含本类以及父类的
getDeclaredFields获取本类中所有属性
getMethods获取所有public修饰的方法,包含本类以及父类
getDeclaredMethods获取本类中所有方法
getConstructors获取本类所有public修饰的构造器,包含本类以及父类
getDeclaredConstructors获取本类中所有构造器
getPackage以Packeage形式返回包信息
getSuperClass以Class形式返回父类信息
getInterfaces以Class[]形式返回接口信息
getAnnotations以Annotation[]形式返回注解信息

  • 第二组:java.lang.reflect.Field类

getModifiers以int形式返回修饰符
【说明:默认修饰符是0,public是1,private是2,protected是4,static是8,final是16】,public(1) + static(8) = 9
getType以Class形式返回类型
getName返回属性名
  • 第三组:java.lang.reflect.Method类

getModifiers以int形式返回修饰符
【说明:默认修饰符是0,public是1,private是2,protected是4,static是8,final是16】,public(1) + static(8) = 9
getReturnType以Class形式获取返回类型
getName返回方法名
getParameterTypes以Class[]返回参数类型数组
  • 第四组:java.lang.reflect.Constructor类

getModifiers以int形式返回修饰符
getName返回构造器名(全类名)
getParameterTypes以Class[]返回参数类型数组

代码演示

package com22.reflection;

import org.junit.jupiter.api.Test;

import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

/**
 * @ClassName ReflectionUtils
 * @Description 演示如何通过反射获取类的结构信息
 * @Author 甲柒
 * @Date 2023/9/12 15:18
 * @Version 1.0
 **/
public class ReflectionUtils {
    public static void main(String[] args) {

    }

    //第二组方法
    @Test
    public void api_02() throws ClassNotFoundException {
        //得到Class对象
        Class<?> personCls = Class.forName("com22.reflection.Person");
        //    getDeclaredFields	获取本类中所有属性
        //  规定 【说明:默认修饰符是0,public是1,private是2,protected是4,static是8,final是16】
        Field[] declaredFields = personCls.getDeclaredFields();
        for (Field declaredField : declaredFields) {
            System.out.println("本类中所有属性=" + declaredField.getName()
                    + " 该属性的修饰符值=" + declaredField.getModifiers()
                    + " 该属性的类型=" + declaredField.getType());
        }

        //    getDeclaredMethods	获取本类中所有方法
        Method[] declaredMethods = personCls.getDeclaredMethods();
        for (Method declaredMethod : declaredMethods) {
            System.out.println("获取本类中所有方法=" + declaredMethod.getName()
                    + " 该方法访问修饰符的值=" + declaredMethod.getModifiers()
                    + " 该方法返回类型=" + declaredMethod.getReturnType());

            //输出当前这个方法的形参数组情况
            Class<?>[] parameterTypes = declaredMethod.getParameterTypes();
            for (Class<?> parameterType : parameterTypes) {
                System.out.println("该方法的形参类型=" + parameterType);
            }
        }

        //    getDeclaredConstructors	获取本类中所有构造器
        Constructor<?>[] declaredConstructors = personCls.getDeclaredConstructors();
        for (Constructor<?> declaredConstructor : declaredConstructors) {
            System.out.println("====================================");
            System.out.println("本类中所有的构造器=" + declaredConstructor.getName());//这里只是输出了名字

            Class<?>[] parameterTypes = declaredConstructor.getParameterTypes();
            for (Class<?> parameterType : parameterTypes) {
                System.out.println("该构造器的形参类型=" + parameterType);
            }

        }
    }

    //第一组方法API
    @Test
    public void api_01() throws ClassNotFoundException {

        //得到Class对象
        Class<?> personCls = Class.forName("com22.reflection.Person");
        //    getName	获取全类名
        System.out.println(personCls.getName());//com22.reflection.Person
        //    getSimpleName	获取简单类名
        System.out.println(personCls.getSimpleName());//Person
        //    getFields	获取所有public修饰的属性,包含本类以及父类的

        Field[] fields = personCls.getFields();
        for (Field field : fields) {
            System.out.println("本类及父类属性=" + field.getName());
        }
        //    getDeclaredFields	获取本类中所有属性
        Field[] declaredFields = personCls.getDeclaredFields();
        for (Field declaredField : declaredFields) {
            System.out.println("本类中所有属性=" + declaredField.getName());
        }
        //    getMethods	获取所有public修饰的方法,包含本类以及父类
        Method[] methods = personCls.getMethods();
        for (Method method : methods) {
            System.out.println("获取所有public修饰的方法,包含本类以及父类=" + method.getName());
        }
        //    getDeclaredMethods	获取本类中所有方法
        Method[] declaredMethods = personCls.getDeclaredMethods();
        for (Method declaredMethod : declaredMethods) {
            System.out.println("获取本类中所有方法=" + declaredMethod.getName());
        }
        //    getConstructors	获取所有public修饰的构造器,包含本类以及父类
        Constructor<?>[] constructors = personCls.getConstructors();
        for (Constructor<?> constructor : constructors) {
            System.out.println("本类以及父类的构造器=" + constructor.getName());
        }
        //    getDeclaredConstructors	获取本类中所有构造器
        Constructor<?>[] declaredConstructors = personCls.getDeclaredConstructors();
        for (Constructor<?> declaredConstructor : declaredConstructors) {
            System.out.println("本类中所有的构造器=" + declaredConstructor.getName());//这里只是输出了名字
        }
        //    getPackage	以Package形式返回包信息
        System.out.println(personCls.getPackage());
        //    getSuperClass	以Class形式返回父类信息
        Class<?> superclass = personCls.getSuperclass();
        System.out.println("父类的class对象=" + superclass);
        //    getInterfaces	以Class[]形式返回接口信息
        System.out.println("====================================");
        Class<?>[] interfaces = personCls.getInterfaces();
        for (Class<?> anInterface : interfaces) {
            System.out.println("接口信息=" + anInterface);
        }
        //    getAnnotations	以Annotation[]形式返回注解信息
        Annotation[] annotations = personCls.getAnnotations();
        for (Annotation annotation : annotations) {
            System.out.println("注解信息=" + annotation);
        }
    }
}

class A {
    public String hobby;

    public void hi() {
    }

    public A() {
    }
}

interface IA {

}

interface IB {

}

//@Deprecated
class Person extends A implements IA, IB {
    //属性
    public String name;
    protected static int age;
    String job;
    private double sal;

    //构造器
    public Person() {
    }

    public Person(String name) {
    }

    public Person(String name, int age) {
    }

    //方法
    public void m1(String name, int age, double sal) {

    }

    protected String m2() {
        return null;
    }

    void m3() {
    }

    private void m4() {
    }

}

运行结果不在演示


通过反射创建对象

  • 方式一:调用类中的public修饰的无参构造器
  • 方式二:调用类中的指定构造器
Class类相关方法
newInstance调用类中的无参构造器,获取对应类的对象
getConstructor(Class...clazz)根据参数列表,获取对应的构造器对象
getDecalaredConstructor(Class..clazz)根据参数列表,获取对应的所有构造器对象




 

Constructor类相关方法
setAccessible暴破
newInstance(Object...obj)调用构造器

案例演示

package com22.reflection;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

/**
 * @ClassName ReflecCreateInstance
 * @Description 演示通过反射机制创建实例
 * @Author 甲柒
 * @Date 2023/9/12 20:29
 * @Version 1.0
 **/
public class ReflecCreateInstance {
    public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
        //1.先获取到User类的Class对象
        Class<?> userClass = Class.forName("com22.reflection.User");

        //2.通过public的无参构造器创建实例
        Object o = userClass.newInstance();
        System.out.println(o);

        //3.通过public的有参构造器创建实例
        /*  constructor就是
            public User(String name) {//public的有参构造器
                this.name = name;
            }
         */
        //3.1先得到对应构造器
        Constructor<?> constructor = userClass.getConstructor(String.class);
        //3.2创建实例,并传入实参
        Object jiaQi = constructor.newInstance("JiaQi");
        System.out.println("JiaQi=" + jiaQi);

        //4.通过非public的有参构造器创建实例
        //4.1得到private的构造器对象
        Constructor<?> constructor1 = userClass.getDeclaredConstructor(int.class, String.class);
        //4.2创建实例
        constructor1.setAccessible(true);//暴破【暴力破解】,使用反射可以访问private构造器/方法/属性,反射面前,都是纸老虎
        Object user2 = constructor1.newInstance(100, "弼马温");
        System.out.println("user2=" + user2);
    }
}

class User {//User类
    private int age = 10;
    private String name = "甲柒";

    public User() {//无参构造器 public

    }

    public User(String name) {//public的有参构造器
        this.name = name;
    }

    private User(int age, String name) {//private的有参构造器
        this.age = age;
        this.name = name;
    }

    @Override
    public String toString() {
        return "User{" +
                "age=" + age +
                ", name='" + name + '\'' +
                '}';
    }
}

运行结果


通过反射访问类中的成员

访问属性 ReflecAccessProperty.java

  1. 根据属性名获取Field对象

    Field f = clazz对象.getDeclaredField(属性名);
     
  2. 暴破

    f.setAccessible(true); //f是Field
     
  3. 访问

    f.set(o,值); //o表示对象

    syso(f.get(o)); //o表示对象
     
  4. 注意:如果是静态属性,则set和get中的参数o,可以写成null

案例演示

package com22.reflection;

import java.lang.reflect.Field;

/**
 * @ClassName ReflecAccessProperty
 * @Description 演示反射操作属性
 * @Author 甲柒
 * @Date 2023/9/12 21:36
 * @Version 1.0
 **/
public class ReflecAccessProperty {
    public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchFieldException {

        //1.得到Student类对应的Class对象
        Class<?> stuClass = Class.forName("com22.reflection.Student");
        //2. 创建对象
        Object o = stuClass.newInstance();//o的运行类型是Student
        System.out.println(o.getClass());//Student
        //3. 使用反射得到age属性对象
        Field age = stuClass.getField("age");
        age.set(o, 88);//通过反射来操作属性
        System.out.println(o);//返回age属性的值

        //4. 使用反射操作name 属性
        Field name = stuClass.getDeclaredField("name");
        //对name进行暴破,可以操作private属性
        name.setAccessible(true);
//        name.set(o, "甲柒");
        name.set(null, "甲柒~~~");//因为name是static属性,因此 o 也可以写成null
        System.out.println(o);
        System.out.println(name.get(o));//获取属性值
        System.out.println(name.get(null));//获取属性值,只有name是静态的才能写成null
    }
}

class Student {//类
    public int age;
    private static String name;

    public Student() {//构造器
    }

    @Override
    public String toString() {
        return "Student{" +
                "age=" + age +
                " name=" + name +
                '}';
    }
}

运行结果

访问方法

  1. 根据方法名和参数列表获取Method方法对象:

    Method m = clazz.getDeclaredMethod(方法名, XX.class);
     
  2. 获取对象:Object  o = clazz.newInstance();
     
  3. 暴破:m.setAccessible(true);
     
  4. 访问:Object returnValue = m.invoke(o, 实参列表);
     
  5. 注意:如果是静态方法,则invoke的参数o,可以写成null

案例演示

package com22.reflection;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * @ClassName ReflecAccessMethod
 * @Description 演示通过反射调用方法
 * @Author 甲柒
 * @Date 2023/9/12 22:50
 * @Version 1.0
 **/
public class ReflecAccessMethod {
    public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {

        //1.得到Boss类对应的Class对象
        Class<?> bossCls = Class.forName("com22.reflection.Boss");
        //2.创建对象
        Object o = bossCls.newInstance();
        //3.调用public的hi方法
//        Method hi = bossCls.getMethod("hi", String.class);//ok
        //3.1得到hi方法对象
        Method hi = bossCls.getDeclaredMethod("hi", String.class);//ok
        //3.2调用
        hi.invoke(o, "甲柒柒");

        //4.调用private static 方法
        //4.1 得到say方法对象
        Method say = bossCls.getDeclaredMethod("say", int.class, String.class, char.class);
        //4.2 因为say方法是private,所以需要暴破
        say.setAccessible(true);
        System.out.println(say.invoke(o, 100, "柒柒柒", '男'));
        //4.3 因为say方法是static的,还可以这样调用
        System.out.println(say.invoke(null, 200, "hongHong", '女'));

        //5. 在反射中如果方法有返回值,统一返回Object,但是他运行类型和方法定义的返回类型一致
        Object reVal = say.invoke(null, 300, "qq", '女');
        System.out.println("reVal 的运行类型=" + reVal.getClass());//String
    }
}

class Boss {//类
    public int age;
    private static String name;

    public Boss() {//无参构造器
    }

    private static String say(int n, String s, char c) {//静态方法
        return n + " " + s + " " + c;
    }

    public void hi(String s) {//
        System.out.println("hi " + s);
    }
}

运行结果

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

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

相关文章

C语言_指针进阶(下)

文章目录 前言一、函数指针数组二、指向函数指针数组的指针三. 回调函数四. qsort 函数五. 数组名的理解 sizeof5.1 数组名的理解&#xff08;二维数组)5.1.1 数组名的理解 strlen5.1.2 例题&#xff1a;例一.例二.例三.例四. 前言 一、函数指针数组 数组是一个存放相同类型数…

LVS负载均衡群集(NAT模式、IP隧道模式、DR模式)

目录 一、集群 1.1 含义即特点 1.2 群集的类型 1.3 LVS 的三种工作模式&#xff1a; 1.4 LVS 调度算法 1.5 负载均衡群集的结构 1.6 ipvsadm 工具 二、NAT模式 LVS-NAT模式配置步骤&#xff1a; 实例&#xff1a; 配置NFS服务器192.168.20.100 配置web1服务器192.168…

C++ istringstream类学习

istringstream类用于执行C风格的串流的输入操作&#xff1b; ostringstream类用于执行C风格的串流的输出操作&#xff1b; strstream类同时可以支持C风格的串流的输入输出操作&#xff1b; istringstream的构造函数原形如下&#xff1a; istringstream::istringstream(strin…

Tomcat Arbitrary Write-file Vulnerability through PUT Method (CVE-2017-12615)

漏洞描述 CVE-2017-12615 对应的漏洞为任意文件写入&#xff0c;由于配置不当&#xff08;非默认配置&#xff09;&#xff0c;导致可以使用 PUT 方法上传任意文件 。Tomcat设置了写权限&#xff08;readonlyfalse&#xff09;&#xff0c;导致可以使用PUT方法上传任意文件 影…

mysql 快速上传数据

快速上传数据 这个应该是比inset into values更快的插入数据的办法了。 不过要求挺苛刻的&#xff0c;数据要整理成和表格一致&#xff0c;也就是说每条数据都是完整的一条&#xff0c;而不是一部分。 下面的示例我以***为分割符划分字段&#xff0c;以 \n来分割每条数据。 LO…

代码随想录笔记--贪心算法篇

1--贪心算法 主要思路&#xff1a; 通过局部最优推导全局最优&#xff1b; 2--分发饼干 主要思路&#xff1a; 基于贪心算法&#xff0c;每次都尽可能用大的饼干去喂胃口大的孩子&#xff0c;贪心地节省饼干&#xff1b; #include <iostream> #include <vector> #i…

5.后端·新建子模块与开发(自动模式)

文章目录 学习资料自动生成模式创建后端三层 学习资料 https://www.bilibili.com/video/BV13g411Y7GS?p11&spm_id_frompageDriver&vd_sourceed09a620bf87401694f763818a31c91e 自动生成模式创建后端三层 首先&#xff0c;运行起来若依的前后端整个项目&#xff0c;…

【Java 基础篇】Java 自然排序:使用 Comparable 接口详解

在 Java 编程中&#xff0c;我们经常需要对对象进行排序。为了实现排序&#xff0c;Java 提供了 java.lang.Comparable 接口&#xff0c;它允许我们定义对象之间的自然顺序。本篇博客将深入探讨如何使用 Comparable 接口来进行自然排序&#xff0c;包括接口的基本概念、使用示例…

【2023年11月第四版教材】第12章《质量管理》(第三部分)

第12章《质量管理》&#xff08;第三部分&#xff09; 5 管理质量5.1 管理质量★★★ &#xff08;17下9&#xff09;5.2 数据分析★★★5.3 数据表现★★★5.4 审计★★★ 6 控制质量6.1 控制质量6.2 数据收集★★★6.3 数据分析 ★★★6.4 数据表现★★★ 5 管理质量 组过程…

《gRPC vs REST:何时选择哪一个》

&#x1f337;&#x1f341; 博主猫头虎&#xff08;&#x1f405;&#x1f43e;&#xff09;带您 Go to New World✨&#x1f341; &#x1f405;&#x1f43e;猫头虎建议程序员必备技术栈一览表&#x1f4d6;&#xff1a; &#x1f6e0;️ 全栈技术 Full Stack: &#x1f4da…

C++--day5

实现一个图形类&#xff08;Shape&#xff09;&#xff0c;包含受保护成员属性&#xff1a;周长、面积&#xff0c; 公共成员函数&#xff1a;特殊成员函数书写 定义一个圆形类&#xff08;Circle&#xff09;&#xff0c;继承自图形类&#xff0c;包含私有属性&#xff1a;半…

Pytorch从零开始实战02

Pytorch从零开始实战——彩色图像识别 本系列来源于365天深度学习训练营 原作者K同学 文章目录 Pytorch从零开始实战——彩色图像识别环境准备数据集模型选择模型训练数据可视化 环境准备 本文基于Jupyter notebook&#xff0c;使用Python3.8&#xff0c;Pytorch2.0.1cu118…

【大数据】美团 DB 数据同步到数据仓库的架构与实践

美团 DB 数据同步到数据仓库的架构与实践 1.背景2.整体架构3.Binlog 实时采集4.离线还原 MySQL 数据5.Kafka2Hive6.对 Camus 的二次开发7.Checkdone 的检测逻辑8.Merge9.Merge 流程举例10.实践一&#xff1a;分库分表的支持11.实践二&#xff1a;删除事件的支持12.总结与展望 1…

Powdersigner + PostgreSql 同步表结构到pg数据库

要用Powdersigner同步表结构到PostgreSql数据库&#xff0c; Powdersigner 版本是 16.5&#xff0c;当前模型是mysql的 1&#xff0c;修改当前模型内容为postgresql的 Database --> Change Current DBMS 选择PostgreSQL 最大版本的&#xff08;因为Powdersigner内置版本一…

Python3 XML处理模块详解

目录 一&#xff1a;XML文件格式 二&#xff1a;ElementTree解析XML文件 三&#xff1a;Element之查找 四&#xff1a;Element之修改 五&#xff1a;Element之删除 六&#xff1a;Element之增加 xml是一种固有的分层数据格式&#xff0c;最自然的表示方式是解析成树状&am…

基于springboot实现的最便捷的解析word文档

概述 导入excel或word是一些web应用常见的需求&#xff0c;本demo详细介绍怎么导入word,读取word里面的数据 详细 一、运行效果 二、实现过程 ①、首先用maven快速搭建一个spring boot 项目 <properties><project.build.sourceEncoding>UTF-8</project.buil…

unity 使用Photon进行网络同步

Pun使用教程 第一步&#xff1a;请确保使用的 Unity 版本等于或高于 2017.4&#xff08;不建议使用测试版&#xff09;创建一个新项目。 第二步&#xff1a;打开资源商店并找到 PUN 2 资源并下载/安装它。 导入所有资源后&#xff0c;让 Unity 重新编译。 第三步&#xf…

stm32---外部中断

一、EXTI STM32F10x外部中断/事件控制器&#xff08;EXTI&#xff09;包含多达20个用于产生事件/中断请求的边沿检测器。EXTI的每根输入线都可单独进行配置&#xff0c;以选择类型&#xff08;中断或事件&#xff09;和相应的触发事件&#xff08;上升沿触发、下降沿触发…

深入理解JVM虚拟机第四篇:一些常用的JVM虚拟机

一&#xff1a;Sun Classic VM虚拟机 早在1996年Java1.0版本的时候&#xff0c;Sun公司发布了一款名为Sun classic VM的Java虚拟机&#xff0c;它同时也是世界上第一款商用Java虚拟机&#xff0c;JDK1.4时完全被淘汰。 现在hotspot内置了此虚拟机。 这款虚拟机内部只提供解释器…

入门人工智能 ——使用 tensorflow 训练一个新闻分类模型(6)

入门人工智能 ——使用 tensorflow 训练一个新闻分类模型&#xff08;6&#xff09; 入门人工智能 ——使用 tensorflow 训练一个新闻分类模型使用 tensorflow 训练一个新闻分类模型1. 安装TensorFlow和所需的依赖项。2. 打开收集的新闻数据集构建模型模型训练模型评估保存模型…