【老生常谈】之Java反射机制

在这里插入图片描述

文章目录

  • 序言
  • 一、基本概念
    • 1.1 Java反射机制是什么?
    • 1.2 反射机制功能
    • 1.3 反射机制的优缺点
  • 二、Java反射机制API
    • 2.1 java.lang.Class 类
    • 2.2 java.lang.reflect 包
      • 2.2.1 java.lang.reflect.Constructor
      • 2.2.2 java.lang.reflect.Method
      • 2.2.3 java.lang.reflect.Field
      • 2.2.4 java.lang.reflect.Modifier
  • 三、小结

序言

  通过 Java 的反射机制,小伙伴们可以更深入地控制程序的运行过程。例如,在程序运行时由用户输入一个类名,然后动态获取该类拥有的构造、属性和方法,甚至调用任意类的任意方法。

一、基本概念

1.1 Java反射机制是什么?

  Java 反射机制是 Java 语言的一个重要特性,在学习 Java 反射机制前,小伙伴们应该先了解两个概念:编译期和运行期。编译期是指把源码交给编译器编译成计算机可以执行的文件的过程。在 Java 中也就是把 Java 代码编成 class 文件的过程。编译期只是做了一些翻译功能,并没有把代码放在内存中运行起来,而只是把代码当成文本进行操作,比如检查错误。运行期是把编译后的文件交给计算机执行,直到程序运行结束。也就是说,所谓运行期就把在磁盘中的代码放到内存中执行起来。
  Java 反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;而对于任意一个对象,都能够调用它的任意方法和属性,这种动态获取信息以及动态调用对象方法的功能称为 Java 语言的反射机制。简单来说,反射机制指的是程序在运行时能够获取自身的信息。在 Java 中,只要给定类的名字,就可以通过反射机制来获得类的所有信息。
  Java 反射机制在服务器程序和中间件程序中得到了广泛运用。在服务器端,往往需要根据客户的请求,动态调用某一个对象的特定方法。此外,在 ORM 中间件的实现中,运用 Java 反射机制可以读取任意一个 JavaBean 的所有属性,或者给这些属性赋值。
在这里插入图片描述

1.2 反射机制功能

Java 反射机制主要提供了以下功能,这些功能都位于java.lang.reflect包。

  • 在运行时判断任意一个对象所属的类。
  • 在运行时构造任意一个类的对象。
  • 在运行时判断任意一个类所具有的成员变量和方法。
  • 在运行时调用任意一个对象的方法。
  • 生成动态代理。

  要想知道一个类的属性和方法,必须先获取到该类的字节码文件对象。获取类的信息时,使用的就是 Class 类中的方法。所以,先要获取到每一个字节码文件(.class)对应的 Class 类型的对象。众所周知,所有 Java 类均继承了 Object 类,在 Object 类中定义了一个 getClass() 方法,该方法返回同一个类型为 Class 的对象。例如,下面的示例代码:

// label1为 JLabel 类的对象
Class labelCls = label1.getClass();

  利用 Class 类的对象 labelCls 可以访问 labelCls 对象的描述信息、JLabel 类的信息以及基类 Object 的信息。下表列出了通过反射可以访问的信息:

类型访问方法返回值类型说明
包路径getPackage()Package对象获取该类的存放路径
类名称getName()String对象获取该类的名称
继承类getSuperclass()Class对象获取该类继承的类
实现接口getlnterfaces()Class型数组获取该类实现的所有接口
构造方法getConstructors()Constructor型数组获取所有权限为public的构造方法
getDeclaredContruectors()Constructor对象获取当前对象的所有构造方法
方法getMethods()Methods型数组获取所有权限为public的方法
getDeclaredMethods()Methods对象获取当前对象的所有方法
成员变量getFields()Field型数组获取所有权限为public的成员变量
getDeclareFileds()Field对象获取当前对象的所有成员变量
内部类getClasses()Class型数组获取所有权限为public的内部类
getDeclaredClasses()Class型数组获取所有内部类
内部类的声明类getDeclaringClass()Class对象如果该类为内部类,则返回它的成员类,否则返回null

  如上表所示,在调用 getFields() 和 getMethods() 方法时将会依次获取权限为 public 的字段和变量,然后将包含从超类中继承到的成员变量和方法。而通过 getDeclareFields() 和 getDeclareMethod() 只是获取在本类中定义的成员变量和方法。

1.3 反射机制的优缺点

  • 优点:
    • 通过 Java 反射机制能够运行时动态获取类的实例,大大提高系统的灵活性和扩展性。
    • 可以与 Java 动态编译相结合,可以实现无比强大的功能。
    • 对于 Java 这种先编译再运行的语言,能够让我们很方便的创建灵活的代码,这些代码可以在运行时装配,无需在组件之间进行源代码的链接,更加容易实现面向对象。
  • 缺点:
    • 反射会消耗一定的系统资源,因此,如果不需要动态地创建一个对象,那么就不需要用反射。
    • 反射调用方法时可以忽略权限检查,获取这个类的私有方法和属性,因此可能会破坏类的封装性而导致安全问题。

因此,Java 反射机制在一般的 Java 应用开发中很少使用,即便是 Java EE 阶段也很少使用。

二、Java反射机制API

  实现 Java 反射机制的类都位于 java.lang.reflect 包中,java.lang.Class 类是 Java 反射机制 API 中的核心类。本小节将从这两个方面讲解 Java 反射机制 API。
在这里插入图片描述

2.1 java.lang.Class 类

  java.lang.Class 类是实现反射的关键所在,存在于JDK的java.lang包中,可以通过它获取类的构造函数、方法、字段等信息。Class 类的一个实例表示 Java 的一种数据类型,表示某个类加载后在堆中的对象,包括类、接口、枚举、注解(Annotation)、数组、基本数据类型和 void。Class 没有公有的构造方法,Class 实例是由 JVM 在类加载时自动创建的。在代码中获得 Class 实例可以通过如下代码实现:

// 1. 通过类型class静态变量
Class clz1 = String.class;
String str = "Hello";
// 2. 通过对象的getClass()方法
Class clz2 = str.getClass();

  每一种类型包括类和接口等,都有一个 class 静态变量可以获得 Class 实例。另外,每一个对象都有 getClass() 方法可以获得 Class 实例,该方法是由 Object 类提供的实例方法。Class 类提供了很多方法可以获得运行时对象的相关信息,下面的示例代码展示了其中一些方法。

public class ReflectionTest01 {public static void main(String[] args) {// 1、获得Class实例// 1.1 通过类型class静态变量Class clz1 = String.class;String str = "Hello";// 1.2 通过对象的getClass()方法Class clz2 = str.getClass();// 2、获得int类型Class实例Class clz3 = int.class;// 3、获得Integer类型Class实例Class clz4 = Integer.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());}
}

2.2 java.lang.reflect 包

  java.lang.reflect 包提供了反射中用到类,主要的类说明如下表所示:

类说明
Constructor提供类的构造方法信息
Field提供类或接口中成员变量信息
Method提供类或接口成员方法信息
Array提供动态创建和访问Java数组的方法
Modifier提供类和成员访问修饰符信息

2.2.1 java.lang.reflect.Constructor

  java.lang.reflect.Constructor 表示一个类的构造函数,可以通过它创建对象。在Java反射机制中,Constructor 对象表示一个类的构造函数,可以用来创建该类的实例对象。通过下列任意一个方法访问能够动态获取对象构造方法的信息,如下所示:

Constructor<?>[] getConstructors()
// 获取该类的指定构造函数 
Constructor<?>[] getConstructor(Class<?>… parameterTypes)
Constructor<?>[] getDeclaredConstructors()
// 获取该类的指定构造函数,不考虑其访问权限
Constructor<?>[] getDeclaredConstructor(Class<?>... parameterTypes)

  使用 Constructor 类可以通过反射机制来创建一个类的实例对象,可以方便地调用私有构造函数等。创建的每个 Constructor 对象表示一个构造方法,然后利用 Constructor 对象的方法操作构造方法。Constructor 类的常用方法如下表所示:

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

下面通过一个案例来演示如何调用 Constructor 类的方法获取构造方法的信息。

  1. 首先创建一个 Book 类表示图书信息。在该类中声明一个 String 型变量表示图书名称,两个 int 型变量分别表示图书编号和价格,并提供 3 个构造方法。如下:

    public class Book {// 图书名称String name;// 图书编号int id;// 图书价格int price;// 空的构造方法private Book() {}// 带两个参数的构造方法protected Book(String name, int id) {this.name = name;this.id = id;}// 带可变参数的构造方法public Book(String... strings) throws NumberFormatException {if (0 < strings.length){id = Integer.valueOf(strings[0]);}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);}
    }
    
  2. 编写测试类 Test01,在该类的 main() 方法中通过反射访问 Book 类中的所有构造方法,并将该构造方法是否带可变类型参数、入口参数类型和可能拋出的异常类型信息输出到控制台。

    public class Test01 {public static void main(String[] args) {// 获取动态类BookClass book = Book.class;// 获取Book类的所有构造方法Constructor[] declaredContructors = book.getDeclaredConstructors();// 遍历所有构造方法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");}}
    }
    
  3. 运行测试类 Test01。

2.2.2 java.lang.reflect.Method

  java.lang.reflect.Method 表示一个类的方法,可以通过它调用类的方法。Method类是用于表示类或接口的方法的反射机制类。它包含有关方法名称,参数类型,返回类型,访问修饰符等信息的元数据。通过下列任意一个方法访问能够动态获取一个对象方法的信息,如下所示:

Method[] getMethods()
// 返回具有指定名称和参数类型的公共方法
Method getMethods(String name,Class<?> …parameterTypes)
Method[] getDeclaredMethods()
// 返回具有指定名称和参数类型的方法,无论是否为公共方法
Method getDeclaredMethods(String name,Class<?>...parameterTypes)

  使用Method类,可以在运行时动态地调用类的方法,而无需在编译时知道类的确切类型。一旦获得了Method对象,就可以使用invoke()方法调用它来执行方法,需要提供目标对象和方法的参数。Method 类的常用方法如下表所示:

方法名称说明
getName()获取该方法的名称
getParameterType()按照声明顺序以 Class 数组的形式返回该方法各个参数的类型
getReturnType()以 Class 对象的形式获得该方法的返回值类型
getExceptionTypes()以 Class 数组的形式获得该方法可能抛出的异常类型
invoke(Object obj,Object…args)利用 args 参数执行指定对象 obj 中的该方法,返回值为 Object 类型
isVarArgs()查看该方法是否允许带有可变数量的参数,如果允许返回 true,否则返回 false
getModifiers()获得可以解析出该方法所采用修饰符的整数。
默认修饰符是0,public是1,private是2,protected是4,static是8,final是16

下面通过一个案例来演示如何调用 Method 类的方法获取动态类中方法的信息。

  1. 首先创建一个 Book1 类,并编写 4 个具有不同作用域的方法,代码如下:

    public class Book1 {// static 作用域方法static void staticMethod() {System.out.println("执行staticMethod()方法");}// public 作用域方法public int publicMethod(int i) {System.out.println("执行publicMethod()方法");return 100 + i;}// protected 作用域方法protected int protectedMethod(String s, int i) throws NumberFormatException {System.out.println("执行protectedMethod()方法");return Integer.valueOf(s) + i;}// private 作用域方法private String privateMethod(String... strings) {System.out.println("执行privateMethod()方法");StringBuffer sb = new StringBuffer();for (int i = 0; i < sb.length(); i++) {sb.append(strings[i]);}return sb.toString();}
    }
    
  2. 编写测试类 Test02,在该类的 main() 方法中通过反射访问 Book1 类中的所有方法,并将该方法是否带可变类型参数、入口参数类型和可能拋出的异常类型信息输出到控制台,代码如下:

    public class Test02 {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); // 设置为允许访问private方法isTurn = true;}}System.out.println("=============================\n");}}
    }
    
  3. 运行测试类 test02,程序将会依次动态访问 Book1 类中的所有方法。

2.2.3 java.lang.reflect.Field

  java.lang.reflect.Field 表示一个类的字段,可以通过它获取和设置类的属性值。Field类代表类或接口的字段,即类或接口中的变量。Field类提供了访问和操作字段的方法,包括获取字段的名称、类型、修饰符、值等。通过下列任意一个方法访问成员变量时将返回 Field 类型的对象或数组,如下所示:

Field[] getFields()
// 获取该类的指定公共字段
Field getField(String name)
Field[] getDeclaredFields()
// 获取该类的指定字段,不考虑其访问权限
Field getDeclaredField(String name)

  Field类是通过Java反射机制来实现的,反射机制是一种在运行时分析和操作类、接口、方法、字段等程序构件的机制。使用反射机制,可以在运行时获取一个类的信息,包括其方法、字段、注解、泛型类型等,并可以动态地创建对象、调用方法、访问字段等。Field 类的常用方法如下表所示:

方法名称说明
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 等私有权限的成员变量
getModifiers()获得可以解析出该方法所采用修饰符的整数。
默认修饰符是0,public是1,private是2,protected是4,static是8,final是16

下面通过一个案例来演示如何调用 Field 类的方法获取动态类中各个成员的信息。

  1. 首先创建一个 Book2 类,在该类中依次声明一个 String、int、float 和 boolean 类型的成员,并设置不同的访问作用域,代码如下:

    public class Book2 {String name;public int id;private float price;protected boolean isLoan;
    }
    
  2. 编写测试类 Test03,在该类的 main() 方法中通过反射访问 Book2 类中的所有成员,并将该成员的名称和类型信息输出到控制台,代码如下:

    import java.lang.reflect.Constructor;
    import java.lang.reflect.Field;
    public class Test03 {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");}}
    }
    
  3. 运行测试类 Test03,程序将会依次动态访问 Book2 类中的所有成员。

2.2.4 java.lang.reflect.Modifier

  通过 java.lang.reflect.Modifier 类可以解析出 getMocMers() 方法的返回值所表示的修饰符信息。在该类中提供了一系列用来解析的静态方法,既可以查看是否被指定的修饰符修饰,还可以字符串的形式获得所有修饰符。Modifier 类的常用静态方法如下表所示:

方法名称说明
isStatic(int mod)如果使用static修饰符修饰则返回true,否则返回false
isPublic(int mod)如果使用public修饰符修饰则返回true,否则返回false
isProtected(int mod)如果使用protected修饰符修饰则返回true,否则返回false
isPrivate(int mod)如果使用private修饰符修饰则返回true,否则返回false
isFinal(int mod)如果使用final修饰符修饰则返回true,否则返回false
toString(int mod)以字符串形式返回所有修饰符

例如,下列代码判断对象 con 所代表的构造方法是否被 public 修饰,以及以字符串形式获取该构造方法的所有修饰符。

// 获取构造方法的修饰符整数
int modifiers = con.getModifiers();
// 判断修饰符整数是否为public 
boolean isPublic = Modifier.isPublic(modifiers);
string allModifiers = Modifier.toString(modifiers);

三、小结

把今天最好的表现当作明天最新的起点…….~

  总之使用反射机制可以实现很多高级功能,比如动态代理、注解处理等。但是,使用反射机制的时候也需要注意一些问题,比如:性能问题和安全问题。因此,在使用反射机制时需要权衡其优缺点,谨慎使用!

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【亲测有效】无法获得下列许可 SOLIDWORKS Standard 无效的(不一致的) 使用许可号码 (-8,544,0)

在观看本文章前&#xff0c;请注意看你的报错代码是否和我的一致&#xff0c;如果不是&#xff0c;直接跳过本文章。 前言&#xff1a;我安装的是SOLIDWORKS2022版&#xff0c;软件已经安装完毕&#xff0c;SolidWorks_Flexnet_Server文件夹里面的两个注册表已经安装完毕&#…

LLM应用开发与落地:使用gradio十分钟搭建聊天UI

一、背景 如果你是做LLM应用开发的&#xff0c;特别是做后端开发&#xff0c;你一定会遇到怎么快速写一个聊天UI界面来调试prompt或agent的问题。这时候的你可能在苦恼中&#xff0c;毕竟react.js, next.js, css, html也不是每个人都那么熟练&#xff0c;对吧&#xff1f;即使…

深度学习入门笔记(七)卷积神经网络CNN

我们先来总结一下人类识别物体的方法: 定位。这一步对于人眼来说是一个很自然的过程,因为当你去识别图标的时候,你就已经把你的目光放在了图标上。虽然这个行为不是很难,但是很重要。看线条。有没有文字,形状是方的圆的,还是长的短的等等。看细节。纹理、颜色、方向等。卷…

Android13源码下载及全编译流程

目录 一、源码下载 1.1、配置要求 1.1.1、硬件配置要求 1.1.2、软件要求 1.2、下载环境搭建 1.2.1、依赖安装 1.2.2、工具安装 1.2.3、git配置 1.2.4、repo配置 1.3、源码下载 1.3.1、明确下载版本 1.3.2、替换为清华源 1.3.3、初始化仓库并指定分支 1.3.4、同步全部源码 二、…

Redis(十一)单线程VS多线程

文章目录 概述为何选择单线程主要性能瓶颈多线程特性和IO多路复用概述Unix网络编程中的五种IO模型Blocking IO-阻塞IONoneBlocking IO-非阻塞IOIO multiplexing-IO多路复用signal driven IO-信号驱动IOasynchronous IO-异步IO 场景&#xff1a;引出epoll总结 开启Redis多线程其…

【Go语言成长之路】安装Go

文章目录 安装Go一、下载Go语言安装包二、删除以前安装的Go版本三、添加/usr/local/go/bin到环境变量内四、确认安装成功 安装Go Note: 这里只演示安装Linux版本的Go&#xff0c;若为其它版本&#xff0c;请按照官网的安装教程进行安装即可。 一、下载Go语言安装包 ​ 在浏览…

paddle环境安装

一、paddle环境安装 如pytorch环境安装一样&#xff0c;首先在base环境下创建一个新的环境来安装paddlepaddle框架。首先创建一个新的环境名叫paddle。执行如下命令。 conda create -n paddle python3.8创建好了名叫paddle这个环境以后&#xff0c;进入到这个环境中&#xff…

STM32--USART串口(2)串口外设

一、USART简介 可配置数据位&#xff1a;不需要校验就是8位&#xff0c;需要校验就选9位&#xff1b; 停止位&#xff1a;决定了帧的间隔; STM32F103C8T6USART&#xff1a;USART1挂载在APB2总线上&#xff0c;USART2和USART3挂载在APB1总线上&#xff1b; 二、USART框图 TXE…

centos 7 部署若依前后端分离项目

目录 一、新建数据库 二、修改需求配置 1.修改数据库连接 2.修改Redis连接信息 3.文件路径 4.日志存储路径调整 三、编译后端项目 四、编译前端项目 1.上传项目 2.安装依赖 3.构建生产环境 五、项目部署 1.创建目录 2.后端文件上传 3. 前端文件上传 六、服务启…

SpringBoot、SpringCloud项目打包,target目录没有生成jar包

Maven中有一个 Execute goals recursively 递归执行 的复选框&#xff0c;如果这个没有勾选在IDEA中本地打包聚合工程的子模块target目录不会生成jar包&#xff0c;递归执行即对聚合工程执行的命令子模块也会执行 clean package install

【Boost】:前置知识(一)

前置知识 一.背景二.下载boost库手册的网页资源三.正排索引和倒排索引四.认识标签和去标签 一.背景 现在知名的搜索引擎&#xff0c;例如&#xff1b;谷歌&#xff0c;百度&#xff0c;搜狐…它们的搜索是属于全网的&#xff0c;而本次的项目是区域搜索。 项目演示 要做的工作…

Spring Framework(6.x)源码编译与源码阅读入门

目录 一、Spring Framework 源码获取问题 1.1 Spring Framework 官网 1.2 Spring Framework 源码地址 1.3 关于访问不了GitHub 官网的解决方案 1.3.1 修改本地hosts文件 1.3.2 GitHub520 1.3.3 Gitee 导入 二、Spring Framework 源码编译 2.1 环境说明 2.1.1 JDK版本 …