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

Java高手的30k之路|面试宝典|精通泛型

泛型

知识点

在Java高级开发中,掌握泛型(Generics)是非常重要的,它是Java语言中的一项重要特性,提供了编译时类型安全检查机制,使得代码更加灵活和可重用。以下是Java高级开发需要掌握的泛型知识点:

  1. 泛型基础

    • 理解泛型的定义和基本语法,包括泛型类、泛型方法、泛型接口。
    • 泛型用法示例:class MyClass<T> {}public <T> void myMethod(T t) {}
  2. 泛型通配符

    • 理解 <?><? extends T><? super T> 等通配符的含义和使用场景。
    • 了解上界通配符和下界通配符在泛型方法和泛型类中的应用。
  3. 泛型和继承关系

    • 理解泛型在继承和子类化中的表现,包括泛型类的继承、通配符的上下界限定。
  4. 类型擦除

    • 理解Java泛型的类型擦除机制,即在运行时泛型类型信息被擦除为原始类型。
    • 泛型类和泛型方法在编译后如何处理为非泛型形式的字节码。
  5. 泛型和集合

    • 熟悉Java集合框架中泛型的应用,如 List<T>Map<K, V> 等。
    • 掌握使用泛型提高集合类型安全性的方法。
  6. 泛型方法

    • 理解泛型方法的定义和使用,以及与泛型类的区别。
    • 了解泛型方法如何在静态方法和实例方法中应用。
  7. 泛型的好处

    • 掌握泛型的优势,如提高代码的类型安全性、避免类型转换错误、增加代码的可读性和重用性等。
  8. 泛型和反射

    • 理解泛型和反射的结合使用,如何通过反射获取泛型信息。
  9. 泛型约束

    • 熟悉泛型的类型约束,如泛型的边界限定(extends 和 super 关键字)。
  10. 泛型和异常

    • 了解泛型和异常处理的结合使用,如何处理泛型异常。

使用

1. 泛型类和泛型接口

限定类型可以在定义泛型类和泛型接口时使用。

// 限定类型 T 必须是 Number 的子类
public class NumberBox<T extends Number> {private T content;public void setContent(T content) {this.content = content;}public T getContent() {return content;}
}// 泛型接口示例
public interface NumberProcessor<T extends Number> {void process(T number);
}

2. 泛型方法

在定义泛型方法时,可以使用限定类型来约束方法的类型参数。

public class Utility {// 泛型方法,限定类型 T 必须是 Number 的子类public static <T extends Number> void printNumber(T number) {System.out.println("Number: " + number);}
}

3. 泛型通配符

限定类型也可以在泛型通配符中使用,以表示方法参数或返回值的类型约束。

import java.util.List;public class WildcardExample {// 通配符上限,list 中的元素必须是 Number 的子类public static void printNumbers(List<? extends Number> list) {for (Number number : list) {System.out.println(number);}}// 通配符下限,list 中的元素必须是 Integer 的父类public static void addIntegers(List<? super Integer> list) {list.add(1);list.add(2);}
}

4. 多重限定

如果类型参数需要同时满足多个接口,可以使用 & 符号进行多重限定。

// T 必须同时实现 Comparable<T> 和 Serializable 接口
public class MultiBound<T extends Comparable<T> & Serializable> {private T content;public void setContent(T content) {this.content = content;}public T getContent() {return content;}
}

5. 示例业务场景

下面通过一些具体的业务场景示例来说明限定类型的使用。

示例 1: 数据处理器

假设我们有一个数据处理器,需要处理不同类型的数值数据,我们可以使用泛型类来实现。

public class DataProcessor<T extends Number> {private T data;public DataProcessor(T data) {this.data = data;}public void process() {System.out.println("Processing data: " + data);}public T getData() {return data;}
}public class Main {public static void main(String[] args) {DataProcessor<Integer> intProcessor = new DataProcessor<>(100);intProcessor.process();DataProcessor<Double> doubleProcessor = new DataProcessor<>(99.99);doubleProcessor.process();}
}
示例 2: 数字打印工具

我们可以使用泛型方法来创建一个打印数字的工具方法。

public class PrintUtil {public static <T extends Number> void print(T number) {System.out.println("Number: " + number);}public static void main(String[] args) {print(123); // Integerprint(45.67); // Double}
}
示例 3: 集合操作工具

使用泛型通配符来创建一个工具类,用于操作集合中的元素。

import java.util.List;
import java.util.ArrayList;public class CollectionUtil {public static void printNumbers(List<? extends Number> list) {for (Number number : list) {System.out.println("Number: " + number);}}public static void addNumbers(List<? super Integer> list) {list.add(10);list.add(20);}public static void main(String[] args) {List<Integer> intList = new ArrayList<>();addNumbers(intList);printNumbers(intList);}
}

结合具体场景的最佳实践

当然可以。以下是结合具体业务场景的Java泛型最佳实践讲解:

1. 确保类型安全

业务场景:一个电商系统需要存储和处理不同类型的订单(如书籍订单和电子产品订单)。

示例

class Order { /*...*/ }
class BookOrder extends Order { /*...*/ }
class ElectronicsOrder extends Order { /*...*/ }List<Order> orders = new ArrayList<>();
orders.add(new BookOrder());
orders.add(new ElectronicsOrder());
// orders.add(new String()); // 编译时会报错,防止插入非订单类型

通过使用泛型,确保集合中只存储订单对象,防止错误类型的插入。

2. 使用通配符提高代码灵活性

业务场景:需要处理一个包含各种类型商品的库存。

上界通配符(Producer-Extends)

public void printInventory(List<? extends Product> inventory) {for (Product p : inventory) {System.out.println(p.getName());}
}List<Book> books = new ArrayList<>();
List<Electronic> electronics = new ArrayList<>();
printInventory(books);
printInventory(electronics);

通过上界通配符,可以处理各种类型的商品清单。

下界通配符(Consumer-Super)

public void addElectronics(List<? super Electronics> inventory) {inventory.add(new Electronics());inventory.add(new Smartphone()); // Smartphone extends Electronics,注意这里可以添加三种类:父类,自己,子类(多态)
}List<Product> products = new ArrayList<>();
addElectronics(products);

通过下界通配符,可以向商品列表中添加各种电子产品。

3. 避免使用原始类型

业务场景:一个社交媒体应用需要存储用户评论。

示例

List<Comment> comments = new ArrayList<>();
comments.add(new Comment("Great post!"));
// comments.add(new User()); // 编译时会报错,防止插入非评论类型

通过使用泛型,确保集合中只包含评论对象。

4. 使用泛型方法提高代码重用性

业务场景:一个文件处理系统,需要打印不同类型的文件内容。

示例

public <T> void printFiles(T[] files) {for (T file : files) {System.out.println(file.toString());}
}Document[] documents = {new Document("Doc1"), new Document("Doc2")};
Image[] images = {new Image("Image1"), new Image("Image2")};
printFiles(documents);
printFiles(images);

通过使用泛型方法,可以打印任何类型的文件内容,提高代码重用性。

5. 使用有界类型参数进行约束

业务场景:一个排行榜系统,需要找到分数最高的用户。

示例

public <T extends Comparable<T>> T findTopScorer(T[] scores) {T top = scores[0];for (T score : scores) {if (score.compareTo(top) > 0) {top = score;}}return top;
}Integer[] intScores = {85, 92, 88};
Double[] doubleScores = {85.5, 92.3, 88.9};
System.out.println(findTopScorer(intScores)); // 输出92
System.out.println(findTopScorer(doubleScores)); // 输出92.3

通过使用有界类型参数,可以确保数组中的元素可以比较,从而找到最高分数。

6. 避免使用泛型类型的静态成员

业务场景:一个用户管理系统,需要存储用户信息。

示例

public class UserManager<T> {private T user;// private static T instance; // 编译错误,避免使用泛型类型的静态成员
}

通过避免使用泛型类型的静态成员,防止类型擦除带来的问题。

7. 使用类型令牌解决类型擦除问题

业务场景:一个对象工厂,需要根据类型创建对象实例。

示例

public <T> T createInstance(Class<T> clazz) throws Exception {return clazz.getDeclaredConstructor().newInstance();
}User user = createInstance(User.class);

通过使用类型令牌,可以在运行时获取泛型类型信息,创建对象实例。

8. 避免在泛型类中使用泛型数组

业务场景:一个订单管理系统,需要存储不同类型的订单。

示例

public class OrderManager<T> {private T[] orders; // 编译错误,避免使用泛型数组private List<T> orderList = new ArrayList<>();
}

通过避免使用泛型数组,防止类型擦除带来的问题。

9. 谨慎使用泛型和异常

业务场景:一个数据处理系统,需要处理不同类型的数据。

示例

// 错误示例
public <T extends Exception> void processData() throws T {// 不能抛出或捕获泛型异常类型
}

避免抛出或捕获泛型异常类型。

10. 使用PECS原则

业务场景:一个物流系统,需要处理和添加不同类型的货物。

示例

// Producer-Extends
public void processCargo(List<? extends Cargo> cargoList) {for (Cargo cargo : cargoList) {System.out.println(cargo.getDetails());}
}// Consumer-Super
public void addCargo(List<? super PerishableCargo> cargoList) {cargoList.add(new PerishableCargo());cargoList.add(new FreshCargo()); // FreshCargo extends PerishableCargo
}List<Cargo> cargos = new ArrayList<>();
addCargo(cargos);

通过PECS原则,可以处理和添加不同类型的货物。

泛型的实现原理及其在运行时的表现

1. 泛型的本质

Java 泛型在编译时提供类型检查和类型安全,允许开发人员编写更灵活且类型安全的代码。然而,在运行时,Java 泛型会被类型擦除(Type Erasure),这意味着所有的类型参数都会被擦除,并替换为它们的限定类型(如果没有指定,则替换为 Object)。

2. 类型擦除(Type Erasure)

类型擦除是 Java 泛型的核心机制。在编译时,编译器会移除泛型类型信息并插入必要的类型转换,以确保类型安全。在运行时,泛型类型信息不存在,所有泛型类型都被替换为原始类型。

例如,以下泛型类:

public class Box<T> {private T content;public void setContent(T content) {this.content = content;}public T getContent() {return content;}
}

在编译后,类型参数 T 会被替换为 Object

public class Box {private Object content;public void setContent(Object content) {this.content = content;}public Object getContent() {return content;}
}

编译器在插入和取出元素时会生成适当的类型转换代码,以确保类型安全。

3. 限定类型

如果泛型类型参数有上限限制,如 T extends Number,类型擦除后会替换为限定类型,而不是 Object

例如:

public class NumberBox<T extends Number> {private T content;public void setContent(T content) {this.content = content;}public T getContent() {return content;}
}

在编译后,类型参数 T 会被替换为 Number

public class NumberBox {private Number content;public void setContent(Number content) {this.content = content;}public Number getContent() {return content;}
}

4. 泛型方法

泛型方法在运行时也会经历类型擦除,其类型参数在运行时被替换为限定类型或 Object

public static <T> void printArray(T[] array) {for (T element : array) {System.out.println(element);}
}

在编译后,类型参数 T 被替换为 Object

public static void printArray(Object[] array) {for (Object element : array) {System.out.println(element);}
}

5. 泛型数组

Java 不允许创建泛型类型的数组,因为在运行时泛型类型被擦除,数组的运行时类型需要具体的类型信息。

以下代码是非法的:

List<String>[] listArray = new List<String>[10]; // 编译错误

解决方法是使用通配符或 Object

List<?>[] listArray = new List<?>[10];

6. 泛型与反射

由于类型擦除,在使用反射时,无法获取泛型类型参数的具体类型信息。例如:

List<String> list = new ArrayList<>();
Type type = list.getClass().getGenericSuperclass();
System.out.println(type); // 输出 java.util.AbstractList<E>

上面的代码只能得到泛型类型参数 E,而不是具体的 String 类型。

为什么输出 java.util.AbstractList<E>

ArrayList 继承自 AbstractList,而 AbstractList 又是AbstractCollection 的子类。具体的继承关系如下:

  • ArrayList<E> extends AbstractList<E>
  • AbstractList<E> extends AbstractCollection<E>

当你调用 list.getClass().getGenericSuperclass() 时,getGenericSuperclass() 方法返回的是直接父类的类型,即 AbstractList<E>。这个类型包含泛型信息,但因为泛型类型参数 E 是在编译时擦除的,实际运行时显示的是泛型类型 E

小结

Java 泛型通过类型擦除实现,在编译时确保类型安全,但在运行时移除类型信息。类型擦除机制使得 Java 泛型在运行时没有性能开销,并且与非泛型代码兼容。然而,这也导致在运行时无法获取具体的泛型类型信息,需要通过其他方式(如反射)来处理泛型类型。

类型擦除的例外

在 Java 中,泛型类型信息确实会在编译期间被擦除,这就是所谓的类型擦除(type erasure)。类型擦除的基本概念是:泛型参数类型在编译时被替换为它们的非泛型上界(通常是 Object,除非有特定的边界),并在必要时插入类型转换。类型擦除的结果是,在运行时,泛型参数的实际类型信息是不可用的。然而,有一些情况下,类型信息是可以保留的,主要依赖于编译器在生成 class 文件时的额外信息。以下是几种情况:

  • 字段:类的字段声明为泛型时,泛型信息会存储在 class 文件的字段信息部分。
  • 方法参数和返回类型:方法参数或返回类型使用泛型时,泛型信息会存储在 class 文件的方法签名部分。
  • 类和接口:类或接口本身声明为泛型时,泛型信息会存储在 class 文件的类型信息部分。

1. 字段的泛型类型

当一个类的字段声明为泛型类型时,编译器会将泛型类型的信息存储在 class 文件的字段信息部分。这使得在运行时,通过反射 API 可以获取到这些泛型类型的信息。比如:

import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;public class GenericField {private List<String> stringList;public static void main(String[] args) throws NoSuchFieldException {Field field = GenericField.class.getDeclaredField("stringList");Type genericFieldType = field.getGenericType();if (genericFieldType instanceof ParameterizedType) {ParameterizedType parameterizedType = (ParameterizedType) genericFieldType;Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();for (Type type : actualTypeArguments) {System.out.println(type);}}}
}

在这个示例中,stringList 字段的泛型类型信息在编译期被存储在 class 文件中,虽然在运行时无法直接使用泛型类型,但可以通过反射 API 获取到这些信息。输出结果为 class java.lang.String

2. 方法的泛型参数类型

类似地,当方法的参数或返回类型使用泛型时,编译器会在 class 文件中存储这些泛型信息。在运行时,可以通过反射获取这些信息。比如:

import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;public class GenericMethod {public <T> void printList(List<T> list) {// Method body}public static void main(String[] args) throws NoSuchMethodException {Method method = GenericMethod.class.getMethod("printList", List.class);Type[] genericParameterTypes = method.getGenericParameterTypes();for (Type type : genericParameterTypes) {if (type instanceof ParameterizedType) {ParameterizedType parameterizedType = (ParameterizedType) type;Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();for (Type actualType : actualTypeArguments) {System.out.println(actualType);}}}}
}

在这个示例中,printList 方法的参数 list 的泛型类型信息被存储在 class 文件中,可以在运行时通过反射获取。

总结

类型擦除确实会在运行时丢失泛型参数的具体类型信息,但是编译器会在 class 文件中存储一些必要的泛型信息,使得可以在运行时通过反射获取这些信息。因此,通过 ParameterizedType,可以在运行时获取泛型参数的类型信息,这在某些情况下非常有用。

ParameterizedType

ParameterizedType 是 Java 反射 API 中的一个接口,它表示一个带有实际类型参数的泛型类型。在实际开发中,我们经常会遇到需要在运行时获取泛型类型参数的情况,这时 ParameterizedType 就非常有用。

ParameterizedType 接口用于表示参数化类型。一个参数化类型是指带有实际类型参数的类型,比如 List<String>Map<String, Integer> 等。通过反射 API,可以在运行时获取这些参数化类型的实际类型参数。

常用方法

ParameterizedType 接口定义了一些方法,用于获取参数化类型的详细信息:

  • Type[] getActualTypeArguments():返回实际类型参数的数组。
  • Type getRawType():返回不带泛型参数的原始类型。
  • Type getOwnerType():返回这个类型的所有者类型,如果这个类型是一个内部类的话。

使用示例

下面通过一个具体的例子来说明如何使用 ParameterizedType 获取泛型类型参数。

示例 1:获取类的泛型类型参数
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;public class GenericClass<T> {public static void main(String[] args) {// 使用匿名子类来保留泛型类型信息GenericClass<List<String>> instance = new GenericClass<List<String>>() {};Type superclass = instance.getClass().getGenericSuperclass();if (superclass instanceof ParameterizedType) {ParameterizedType parameterizedType = (ParameterizedType) superclass;Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();for (Type type : actualTypeArguments) {System.out.println(type);}}}
}

在这个示例中,通过创建 GenericClass 的匿名子类,我们保留了泛型类型信息。然后使用反射获取泛型类型参数,输出结果为 java.util.List<java.lang.String>

示例 2:获取方法的泛型类型参数
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;public class GenericMethod {public <T> void printList(List<T> list) {// Method body}public static void main(String[] args) throws NoSuchMethodException {Method method = GenericMethod.class.getMethod("printList", List.class);Type[] genericParameterTypes = method.getGenericParameterTypes();for (Type type : genericParameterTypes) {if (type instanceof ParameterizedType) {ParameterizedType parameterizedType = (ParameterizedType) type;Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();for (Type actualType : actualTypeArguments) {System.out.println(actualType);}}}}
}

在这个示例中,我们通过反射获取了泛型方法 printList 的类型参数,输出结果为 T

示例 3:获取字段的泛型类型参数
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;public class GenericField {private List<String> stringList;public static void main(String[] args) throws NoSuchFieldException {Field field = GenericField.class.getDeclaredField("stringList");Type genericFieldType = field.getGenericType();if (genericFieldType instanceof ParameterizedType) {ParameterizedType parameterizedType = (ParameterizedType) genericFieldType;Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();for (Type type : actualTypeArguments) {System.out.println(type);}}}
}

在这个示例中,我们通过反射获取了泛型字段 stringList 的类型参数,输出结果为 java.lang.String

相关文章:

Java高手的30k之路|面试宝典|精通泛型

泛型 知识点 在Java高级开发中&#xff0c;掌握泛型&#xff08;Generics&#xff09;是非常重要的&#xff0c;它是Java语言中的一项重要特性&#xff0c;提供了编译时类型安全检查机制&#xff0c;使得代码更加灵活和可重用。以下是Java高级开发需要掌握的泛型知识点&#…...

清理Linux操作系统buff/cache缓存

清理Linux操作系统buff/cache缓存 清理页缓存 echo 1 > /proc/sys/vm/drop_caches 或者 sysctl -w vm.drop_caches1 清理目录项和inode缓存 echo 2 > /proc/sys/vm/drop_caches 或者 sysctl -w vm.drop_caches2 同时清理页缓存、目录项和inode缓存 echo 3 > /pr…...

接口测试的几种方法

其实无论用那种测试方法&#xff0c;接口测试的原理是通过测试程序模拟客户端向服务器发送请求报文&#xff0c;服务器接收请求报文后对相应的报文做出处理然后再把应答报文发送给客户端&#xff0c;客户端接收应答报文这一个过程。 方法一、用LoadRunner实现接口测试 大家都…...

OpenGL3.3_C++_Windows(3)

GLSL Shader基础 Shader&#xff08;把输入转化为输出,运行在GPU上&#xff09;&#xff1a;首先要声明版本&#xff0c;有各自的入口点main&#xff08;&#xff09;顶点数据上限:16个包含4分量&#xff1a;16 * 4 64个分量向量&#xff1a;容器vec。使用.x、.y、.z和.w&am…...

24执业药师报名时间汇总及报名流程!

24执业药师报名时间汇总&#xff01;报名流程&#xff01; &#x1f55b;️各省市报名时间汇总&#xff08;共9地&#xff09; 西藏&#xff1a;6月29日-7月8日 新疆&#xff1a;6月25日10:30-7月9日19:00 内蒙古&#xff1a;6月20日9:00-7月3日24:00 新疆兵团&#xff1a;6月2…...

成都跃享未来教育咨询解锁新篇章

在快节奏的现代社会中&#xff0c;每个人都在追求着属于自己的非凡人生。而成都跃享未来教育咨询&#xff0c;正是那个能够智慧引领你走向成功、成就非凡人生的灯塔。 跃享未来教育咨询&#xff0c;位于历史悠久的文化名城成都&#xff0c;这里不仅有丰富的文化底蕴&#xff0c…...

怎么把网页上的接口信息导入postman

第一步 打开f12&#xff0c;右键选中需要的接口。选择copy-copy as cURL 第二步 打开postman&#xff0c;选择"Raw Text"&#xff0c; 把刚才复制的curl粘贴到空白位置&#xff0c;点击Continue - 最后的效果。导入的接口自带cookie&#xff0c;不用再输入cookie&a…...

10KM无人机高清图传通信模组,低延迟、抗干扰,飞睿智能无线MESH组网模块

随着科技的飞速发展&#xff0c;无人机技术在各个领域的应用越来越广泛。尤其在海上监测、搜索救援、货物运输等场景中&#xff0c;无人机的应用显得尤为重要。然而&#xff0c;要实现无人机在复杂海域环境中的高效通信&#xff0c;高清图传通信模组的作用不可忽视。本文将深入…...

分布式文件存储 - - - MinIO从入门到飞翔

MinIO从入门到飞翔 文章目录 MinIO从入门到飞翔0、前言1、分布式文件系统2、MinIO 介绍3、 MinIO安装&#xff08;docker&#xff09;4、基本概念5、通过代码上传文件到MinIO6、封装MinIO为starter7、在其他项目中集成封装好的模块 0、前言 对象存储是一种数据存储架构&#x…...

Python界面编辑器Tkinter布局助手 使用体验

一、发现 我今天在网上搜关于Python Tkinter方面的信息时&#xff0c;发现了Python界面编辑器 Tkinter布局助手 的使用说明。 https://blog.csdn.net/weixin_52777652/article/details/135291731?spm1001.2014.3001.5506 这个编辑器是个开源的项目&#xff0c;个人用户可以…...

嵌入式操作系统_2.嵌入式操作系统的一般架构

1.嵌入式操作系统的概念 嵌入式操作系统通常由硬件驱动程序、调式代理、操作系统内核、文件系统和可配置组件等功能组成&#xff0c;并为应用软件提供标准的API&#xff08;Application Programming Interface&#xff09;接口服务。 2.一般嵌入式操作系统的体系结构 从嵌入…...

docker 容器 network host 模式启动

docker 默认启动容器 network 是 bridge 模式&#xff0c;需使用 -p 映射端口实现容器与宿主机网络通信&#xff0c;较安全&#xff1b; 当使用 network host 模式&#xff0c;直接走宿主机网络通信&#xff0c;较不安全。 下面来一个 docker 容器 network host 模式启动 的 实…...

群晖NAS安装配置Joplin Server用来存储同步Joplin笔记内容

一、Joplin Server简介 1.1、Joplin Server介绍 Joplin支持多种方式进行同步用户的笔记数据&#xff08;如&#xff1a;Joplin自己提供的收费的云服务Joplin Cloud&#xff0c;还有第三方的云盘如Dropbox、OneDrive&#xff0c;还有自建的云盘Nextcloud、或者通过WebDAV协议来…...

leetcode-08-[151]翻转字符串里的单词[卡码网55]右旋转字符串

一、[151]翻转字符串里的单词 重点&#xff1a;见注释 class Solution {public String reverseWords(String s) {//1、移除多余的空格StringBuilder stringBuilder removeSpace(s);//2、反转整个字符串reverse(stringBuilder,0,stringBuilder.length()-1);//3、反转每个单词…...

Json-server 的使用教程

目录 前言一、简介二、安装与配置1. 安装 node-js2. npm 镜像设置3. 安装 json-server 三、使用1. 创建本地数据源2. 启动 Json Server3. 操作数据&#xff08;1&#xff09;查询数据&#xff08;2&#xff09;新增数据&#xff08;3&#xff09;修改数据&#xff08;4&#xf…...

LLM中表格处理与多模态表格理解

文档处理中不可避免的遇到表格&#xff0c;关于表格的处理问题&#xff0c;整理如下&#xff0c;供各位参考。 问题描述 RAG中&#xff0c;对上传文档完成版式处理后进行切片&#xff0c;切片前如果识别文档元素是表格&#xff0c;那么则需要对表格进行处理。一般而言&#x…...

短剧系统搭建全攻略:功能齐全,一步到位

前言 近年来&#xff0c;短剧系统以其独特魅力&#xff0c;成为大众消遣娱乐的热门选择。简单来说&#xff0c;短剧系统就是用来看短剧的小程序&#xff0c;它汇集了丰富多彩的短剧资源&#xff0c;让观众随时随地享受观影乐趣。本文将为你详细解析短剧系统的搭建全攻略&#…...

【Linux】进程_7

文章目录 五、进程8. 进程地址空间9. 进程终止10. 进程等待 未完待续 五、进程 8. 进程地址空间 我们上节知道了进程地址空间是根据页表来使虚拟地址转换成内存中的物理地址&#xff0c;那这种 地址空间 页表 的机制有什么好处呢&#xff1f;①这种机制可以将物理内存从无序…...

从中概回购潮,看互联网的未来

王兴的饭否语录里有这样一句话&#xff1a;“对未来越有信心&#xff0c;对现在越有耐心。” 而如今的美团&#xff0c;已经不再掩饰对未来的坚定信心。6月11日&#xff0c;美团在港交所公告&#xff0c;计划回购不超过20亿美元的B类普通股股份。 而自从港股一季度财报季结束…...

【OceanBase DBA早下班系列】—— 性能问题如何 “拍CT“ (一键获取火焰图和扁鹊图)

1. 前言 最近接连遇到几个客户的环境在排查集群性能问题&#xff0c;总结了一下&#xff0c;直接教大家如何去获取火焰图、扁鹊图&#xff08;调用关系图&#xff09;&#xff0c;直击要害&#xff0c;就像是内脏的疾病去医院看病&#xff0c;上来先照一个CT&#xff0c;通过分…...

MPNet:旋转机械轻量化故障诊断模型详解python代码复现

目录 一、问题背景与挑战 二、MPNet核心架构 2.1 多分支特征融合模块(MBFM) 2.2 残差注意力金字塔模块(RAPM) 2.2.1 空间金字塔注意力(SPA) 2.2.2 金字塔残差块(PRBlock) 2.3 分类器设计 三、关键技术突破 3.1 多尺度特征融合 3.2 轻量化设计策略 3.3 抗噪声…...

Zustand 状态管理库:极简而强大的解决方案

Zustand 是一个轻量级、快速和可扩展的状态管理库&#xff0c;特别适合 React 应用。它以简洁的 API 和高效的性能解决了 Redux 等状态管理方案中的繁琐问题。 核心优势对比 基本使用指南 1. 创建 Store // store.js import create from zustandconst useStore create((set)…...

MySQL中【正则表达式】用法

MySQL 中正则表达式通过 REGEXP 或 RLIKE 操作符实现&#xff08;两者等价&#xff09;&#xff0c;用于在 WHERE 子句中进行复杂的字符串模式匹配。以下是核心用法和示例&#xff1a; 一、基础语法 SELECT column_name FROM table_name WHERE column_name REGEXP pattern; …...

智能仓储的未来:自动化、AI与数据分析如何重塑物流中心

当仓库学会“思考”&#xff0c;物流的终极形态正在诞生 想象这样的场景&#xff1a; 凌晨3点&#xff0c;某物流中心灯火通明却空无一人。AGV机器人集群根据实时订单动态规划路径&#xff1b;AI视觉系统在0.1秒内扫描包裹信息&#xff1b;数字孪生平台正模拟次日峰值流量压力…...

【C++从零实现Json-Rpc框架】第六弹 —— 服务端模块划分

一、项目背景回顾 前五弹完成了Json-Rpc协议解析、请求处理、客户端调用等基础模块搭建。 本弹重点聚焦于服务端的模块划分与架构设计&#xff0c;提升代码结构的可维护性与扩展性。 二、服务端模块设计目标 高内聚低耦合&#xff1a;各模块职责清晰&#xff0c;便于独立开发…...

Rapidio门铃消息FIFO溢出机制

关于RapidIO门铃消息FIFO的溢出机制及其与中断抖动的关系&#xff0c;以下是深入解析&#xff1a; 门铃FIFO溢出的本质 在RapidIO系统中&#xff0c;门铃消息FIFO是硬件控制器内部的缓冲区&#xff0c;用于临时存储接收到的门铃消息&#xff08;Doorbell Message&#xff09;。…...

【SpringBoot自动化部署】

SpringBoot自动化部署方法 使用Jenkins进行持续集成与部署 Jenkins是最常用的自动化部署工具之一&#xff0c;能够实现代码拉取、构建、测试和部署的全流程自动化。 配置Jenkins任务时&#xff0c;需要添加Git仓库地址和凭证&#xff0c;设置构建触发器&#xff08;如GitHub…...

pycharm 设置环境出错

pycharm 设置环境出错 pycharm 新建项目&#xff0c;设置虚拟环境&#xff0c;出错 pycharm 出错 Cannot open Local Failed to start [powershell.exe, -NoExit, -ExecutionPolicy, Bypass, -File, C:\Program Files\JetBrains\PyCharm 2024.1.3\plugins\terminal\shell-int…...

aardio 自动识别验证码输入

技术尝试 上周在发学习日志时有网友提议“在网页上识别验证码”&#xff0c;于是尝试整合图像识别与网页自动化技术&#xff0c;完成了这套模拟登录流程。核心思路是&#xff1a;截图验证码→OCR识别→自动填充表单→提交并验证结果。 代码在这里 import soImage; import we…...

pgsql:还原数据库后出现重复序列导致“more than one owned sequence found“报错问题的解决

问题&#xff1a; pgsql数据库通过备份数据库文件进行还原时&#xff0c;如果表中有自增序列&#xff0c;还原后可能会出现重复的序列&#xff0c;此时若向表中插入新行时会出现“more than one owned sequence found”的报错提示。 点击菜单“其它”-》“序列”&#xff0c;…...