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

深入解析:第 9 篇:深入浅出学 Java 语言(JDK8 版)—— 吃透泛型机制,筑牢 Java 类型安全防线

深入解析:第 9 篇:深入浅出学 Java 语言(JDK8 版)—— 吃透泛型机制,筑牢 Java 类型安全防线

简介:聚焦 Java 泛型这一“类型安全保障”核心技术,从泛型解决的核心痛点(非泛型代码的运行时类型错误、强制类型转换冗余)切入,详解泛型的本质(参数化类型)、核心用法(泛型类/接口/方法)、类型通配符(上界/下界/未限定)、类型擦除原理,以及泛型与继承的关系,结合 JDK8 特性(菱形语法、类型推断增强)与场景化代码示例,帮初学者理解泛型如何将类型错误提前到编译时,减少冗余代码,提升代码复用性与稳定性,为后续集合框架、通用组件开发夯实基础。

一、为什么用泛型?—— 解决非泛型的“痛点”

在泛型出现前,Java 用 Object 存储任意类型数据,导致两大问题:运行时类型错误(编译时无法检查类型)和强制类型转换冗余。泛型通过“参数化类型”,让类型成为代码的“参数”,从根本上解决这些问题,带来三大核心优势:

1. 编译时更强的类型检查

非泛型代码中,编译器无法验证集合存储的类型,错误只能在运行时暴露;泛型代码在编译时就会拦截类型不匹配的错误。

示例:非泛型 vs 泛型的类型检查

// 非泛型:编译通过,运行时抛ClassCastException
List nonGenericList = new ArrayList();
nonGenericList.add("Java");
nonGenericList.add(123);
// 编译无错误(Object类型)
String s = (String) nonGenericList.get(1);
// 运行时错误:Integer不能转String
// 泛型:编译时直接报错,提前拦截错误
List<
String> genericList = new ArrayList<
>();
genericList.add("Java");
genericList.add(123);
// 编译错误:不兼容的类型,int无法转String

2. 取消强制类型转换

非泛型代码中,从集合获取元素必须强制转换;泛型代码通过类型参数自动匹配,无需手动转换,减少代码冗余与错误风险。

示例:取消强制转换

// 非泛型:需强制转换
List nonGenericList = new ArrayList();
nonGenericList.add("Hello");
String s1 = (String) nonGenericList.get(0);
// 必须强转
// 泛型:无需转换,编译器自动匹配类型
List<
String> genericList = new ArrayList<
>();
genericList.add("Hello");
String s2 = genericList.get(0);
// 直接获取,无强转

3. 实现泛型算法

泛型允许编写“与类型无关”的通用算法,可复用在不同类型集合上,且保证类型安全。例如,一个排序算法可同时处理 List<Integer>List<String>(只要元素可比较)。

示例:泛型算法(计算大于指定元素的数量)

// 泛型方法:适用于所有实现Comparable的类型
public static <
T extends Comparable<
T>
> int countGreaterThan(T[] arr, T elem) {
int count = 0;
for (T e : arr) {
if (e.compareTo(elem) >
0) {
// 调用Comparable方法,类型安全
count++;
}
}
return count;
}
// 调用:支持Integer、String等可比较类型
Integer[] intArr = {
1, 3, 5, 7
};
System.out.println(countGreaterThan(intArr, 3));
// 输出2(5、7)
String[] strArr = {
"a", "c", "e"
};
System.out.println(countGreaterThan(strArr, "c"));
// 输出1(e)

二、泛型类型:定义泛型类与接口

泛型类型是“参数化的类或接口”,通过 <类型参数> 声明,可在类/接口内部用作字段、方法参数或返回值类型。

1. 泛型类/接口的定义

语法:class/interface 名称<T1, T2, ...> { ... },其中 <T1, T2> 是类型参数(也叫类型变量),代表未知类型,后续可在类体中使用。

示例1:泛型类 Box

/**
* 泛型Box类:存储任意类型的单个对象
* @param <T> 存储对象的类型(Type)
*/
public class Box
<
T> {
private T content;
// 类型参数作为字段类型
// 类型参数作为构造函数参数类型
public Box(T content) {
this.content = content;
}
// 类型参数作为方法返回值和参数类型
public T getContent() {
return content;
}
public void setContent(T content) {
this.content = content;
}
}

示例2:泛型接口 Pair<K, V>

/**
* 泛型接口:存储键值对
* @param <K> 键的类型(Key)
* @param <V> 值的类型(Value)
*/
public interface Pair<
K, V> {
K getKey();
V getValue();
void setKey(K key);
void setValue(V value);
}
// 实现泛型接口
public class OrderedPair
<
K, V> implements Pair<
K, V> {
private K key;
private V value;
public OrderedPair(K key, V value) {
this.key = key;
this.value = value;
}
@Override
public K getKey() {
return key;
}
@Override
public V getValue() {
return value;
}
@Override
public void setKey(K key) {
this.key = key;
}
@Override
public void setValue(V value) {
this.value = value;
}
}

2. 类型参数命名规范

按惯例,类型参数用单个大写字母,便于区分普通类名,常见命名:

  • E:元素(Element,集合框架常用,如 List<E>
  • K:键(Key,如 Map<K, V>
  • V:值(Value,如 Map<K, V>
  • T:类型(Type,通用类型参数)
  • S、U、V:第2、3、4个类型参数

3. 泛型类型的实例化

实例化泛型类时,需指定类型实参(替换类型参数的具体类型),JDK7+ 支持“菱形语法”(<>),编译器可自动推断类型。

示例:实例化泛型类

// JDK7前:需显式指定类型实参
Box<
String> stringBox1 = new Box<
String>("Java泛型");
// JDK7+:菱形语法,编译器从左側推断类型
Box<
String> stringBox2 = new Box<
>("Java菱形语法");
// 多个类型参数的实例化
Pair<
String, Integer> user = new OrderedPair<
>("Alice", 25);
System.out.println("Name: " + user.getKey() + ", Age: " + user.getValue());

4. 原始类型与未检查警告

  • 原始类型:泛型类/接口不带类型参数的形式(如 Box 而非 Box<T>),是为兼容 pre-JDK5 代码保留的特性。
  • 问题:原始类型绕过泛型类型检查,可能导致运行时错误,且编译器会生成“未检查警告”。
  • 建议:除非必须兼容旧代码,否则避免使用原始类型;若无法避免,可通过 @SuppressWarnings("unchecked") 抑制警告(需确保代码安全)。

示例:原始类型的风险

// 原始类型:编译器警告“使用了未经检查或不安全的操作”
Box rawBox = new Box(123);
// 错误:将String赋值给原始类型Box,编译无警告,运行时错误
rawBox.setContent("错误类型");
Integer content = (Integer) rawBox.getContent();
// 运行时ClassCastException

三、泛型方法:定义通用方法

泛型方法是“自身声明类型参数的方法”,类型参数作用域仅限于当前方法,支持静态/非静态方法,甚至构造函数。

1. 泛型方法的定义

语法:[修饰符] <T1, T2, ...> 返回值类型 方法名(参数列表) { ... }类型参数声明必须在返回值类型前

示例1:静态泛型方法(比较两个Pair是否相等)

public class PairUtil
{
/**
* 静态泛型方法:比较两个Pair的键和值是否相等
* @param <K> 键类型
* @param <V> 值类型
* @param p1 第一个Pair
* @param p2 第二个Pair
* @return 相等返回true,否则false
*/
public static <
K, V> boolean equals(Pair<
K, V> p1, Pair<
K, V> p2) {
return p1.getKey().equals(p2.getKey()) && p1.getValue().equals(p2.getValue());
}
}
// 调用:编译器自动推断类型参数为<String, Integer>Pair<String, Integer> p1 = new OrderedPair<>("Alice", 25);Pair<String, Integer> p2 = new OrderedPair<>("Alice", 25);System.out.println(PairUtil.equals(p1, p2));// 输出true

示例2:非静态泛型方法(Box的泛型构造函数)

public class Box
<
T> {
private T content;
// 泛型构造函数(虽未显式声明<T>,但使用类的类型参数)
public Box(T content) {
this.content = content;
}
// 非静态泛型方法:转换Box的类型
public <
U> Box<
U> convert(U newContent) {
return new Box<
>(newContent);
}
}
// 调用非静态泛型方法
Box<
String> stringBox = new Box<
>("Java");
Box<
Integer> intBox = stringBox.convert(123);
// 推断U为Integer

2. 类型推断

编译器可根据方法参数、目标类型自动推断泛型方法的类型参数,无需显式指定(显式指定格式:类名.<T>方法名(参数))。

示例:类型推断的简化调用

// 显式指定类型参数(不推荐,冗余)
boolean eq1 = PairUtil.<
String, Integer>equals(p1, p2);
// 编译器自动推断类型(推荐,简洁)
boolean eq2 = PairUtil.equals(p1, p2);
// 目标类型驱动的类型推断(JDK8+)
List<
String> list = Collections.emptyList();
// 推断为List<String>

3. 有限类型参数(边界约束)

默认情况下,类型参数可代表任何引用类型(如 T 等价于 T extends Object)。通过 extends 关键字可限制类型参数的上界(只能是指定类型或其子类型),支持多个边界(类在前,接口在后,用 & 分隔)。

示例1:单边界(T 必须实现 Comparable)

// 有限类型参数:T必须实现Comparable<T>(可比较)
public static <
T extends Comparable<
T>
> T max(T a, T b) {
return a.compareTo(b) >
0 ? a : b;
}
// 调用:支持Integer、String等实现Comparable的类型
System.out.println(max(3, 5));
// 输出5
System.out.println(max("apple", "banana"));
// 输出"banana"

示例2:多边界(T 必须是 Number 子类且实现 Serializable)

// 多边界:T extends 类 & 接口1 & 接口2(类必须在前)
public static <
T extends Number &
Serializable> void print(T num) {
System.out.println("Value: " + num + ", Class: " + num.getClass().getSimpleName());
}
// 调用:Integer是Number子类且实现Serializable
print(123);
// 输出"Value: 123, Class: Integer"

四、泛型与继承:避免子类型误解

泛型不遵循“类型实参的继承关系”,即若 AB 的子类,List<A> 不是 List<B> 的子类,这是泛型类型安全的关键。

1. 泛型子类型的误区

错误认知IntegerNumber 的子类 → List<Integer>List<Number> 的子类。
正确结论List<Integer>List<Number> 无继承关系,共同父类是 List<?>(通配符类型)。

示例:泛型子类型的错误与后果

List<
Integer> intList = new ArrayList<
>();
// 编译错误:List<Integer>不能赋值给List<Number>List<Number> numList = intList;// 若允许赋值,会导致类型安全问题(实际存储Integer的列表存入Double)numList.add(3.14);// 编译无错,但intList实际存储了DoubleInteger num = intList.get(0);// 运行时ClassCastException

2. 通配符:灵活构建泛型子类型关系

通配符(?)代表“未知类型”,通过结合 extends(上界)和 super(下界),可灵活构建泛型类型间的关系,解决泛型子类型的灵活性问题。

(1)上界通配符:? extends T

代表“未知类型,且是 TT 的子类”,适用于**“输入”变量**(仅读取,不写入,除非写入 null)。

示例:上界通配符计算数字列表总和

// 上界通配符:list元素是Number或其子类(Integer、Double等)
public static double sumOfList(List<
? extends Number> list) {
double sum = 0.0;
for (Number num : list) {
sum += num.doubleValue();
// 调用Number的方法,类型安全
}
return sum;
}
// 调用:支持List<Integer>、List<Double>等List<Integer> intList = Arrays.asList(1, 2, 3);List<Double> doubleList = Arrays.asList(1.1, 2.2, 3.3);System.out.println(sumOfList(intList));// 输出6.0System.out.println(sumOfList(doubleList));// 输出6.6
(2)下界通配符:? super T

代表“未知类型,且是 TT 的超类”,适用于**“输出”变量**(可写入 T 或其子类,读取时仅能当作 Object)。

示例:下界通配符向列表添加整数

// 下界通配符:list元素是Integer或其超类(Number、Object)
public static void addNumbers(List<
? super Integer> list) {
for (int i = 1; i <= 3; i++) {
list.add(i);
// 写入Integer,类型安全
}
}
// 调用:支持List<Integer>、List<Number>、List<Object>List<Number> numList = new ArrayList<>();addNumbers(numList);System.out.println(numList);// 输出[1, 2, 3]
(3)未限定通配符:?

代表“未知类型”,适用于不依赖类型参数的操作(如获取列表大小、清空列表),或仅用 Object 方法访问元素。

示例:未限定通配符打印任意类型列表

// 未限定通配符:list元素类型未知,仅用Object方法
public static void printList(List<
?> list) {
for (Object elem : list) {
System.out.print(elem + " ");
}
System.out.println();
}
// 调用:支持任何类型的List
List<
String> strList = Arrays.asList("a", "b", "c");
List<
Integer> intList = Arrays.asList(1, 2, 3);
printList(strList);
// 输出"a b c "
printList(intList);
// 输出"1 2 3 "
(4)通配符使用指南
  • “输入”变量(仅读取):用 ? extends T(如 sumOfList);
  • “输出”变量(仅写入):用 ? super T(如 addNumbers);
  • 既读又写:不用通配符(直接用 List<T>);
  • 不依赖类型:用 ?(如 printList)。

五、类型擦除:泛型的实现原理

Java 泛型是“编译时技术”,运行时不存在泛型类型信息,编译器通过类型擦除实现泛型,确保兼容性且无运行时开销。

1. 类型擦除的过程

编译器对泛型代码执行以下操作:

  1. 替换类型参数:若类型参数有上界,替换为第一个上界;若无界,替换为 Object
  2. 插入类型转换:若需要,插入强制类型转换以保证类型安全;
  3. 生成桥接方法:若泛型类被继承,生成桥接方法保持多态性。

示例1:泛型类的擦除

// 泛型类Box<T>(无界)
public class Box
<
T> {
private T content;
public T getContent() {
return content;
}
}
// 擦除后:T替换为Object
public class Box
{
private Object content;
public Object getContent() {
return content;
}
}
// 泛型类Box<T extends Comparable<T>>(有界)
public class Box
<
T extends Comparable<
T>
> {
private T content;
public T compare(T other) {
return content.compareTo(other) >
0 ? content : other;
}
}
// 擦除后:T替换为第一个上界Comparable
public class Box
{
private Comparable content;
public Comparable compare(Comparable other) {
return content.compareTo(other) >
0 ? content : other;
}
}

示例2:泛型方法的擦除

// 泛型方法countGreaterThan
public static <
T extends Comparable<
T>
> int countGreaterThan(T[] arr, T elem) {
...
}
// 擦除后:T替换为Comparable
public static int countGreaterThan(Comparable[] arr, Comparable elem) {
...
}

2. 桥接方法:保持泛型多态性

当泛型类被继承且方法被重写时,类型擦除可能导致方法签名不匹配,编译器会生成桥接方法(合成方法)解决此问题。

示例:桥接方法的产生

// 泛型父类Node<T>
public class Node
<
T> {
public void setData(T data) {
...
}
}
// 子类MyNode继承Node<Integer>public class MyNodeextends Node<Integer> {@Overridepublic void setData(Integer data) {...} // 重写setData}// 擦除后:父类Node的setData变为setData(Object),子类MyNode的setData(Integer)不匹配// 编译器生成桥接方法,委托给子类的setData(Integer)public class MyNodeextends Node {// 子类重写的方法public void setData(Integer data) {...}// 编译器生成的桥接方法public void setData(Object data) {setData((Integer) data);// 强制转换后调用子类方法}}

3. 堆污染与 @SafeVarargs

  • 堆污染:参数化类型变量引用非该类型的对象(如 List<String>[] arr = new List[2]; arr[0] = new List<Integer>();),通常由混合原始类型或未检查转换导致。
  • @SafeVarargs 注解:用于泛型可变参数方法,断言方法实现不会不当处理可变参数,抑制“潜在堆污染”警告。

示例:@SafeVarargs 的使用

public class ArrayUtil
{
// 泛型可变参数方法,用@SafeVarargs抑制警告
@SafeVarargs
public static <
T> void addAll(List<
T> list, T... elements) {
for (T elem : elements) {
list.add(elem);
}
}
public static void main(String[] args) {
List<
String> list = new ArrayList<
>();
addAll(list, "a", "b", "c");
// 安全调用,无警告
}
}

六、泛型的限制:避免常见错误

泛型受限于 Java 语言特性,存在以下限制,需理解原因并规避:

限制原因示例(编译错误)
不能实例化类型参数类型擦除后类型参数消失,无法创建实例T elem = new T();
不能声明静态类型参数字段静态字段属于类,类型参数随实例变化,冲突public class Box<T> { private static T content; }
不能用 instanceof 检查泛型类型类型擦除后无泛型信息,无法区分if (list instanceof List<Integer>) { ... }
不能创建泛型类型数组数组运行时检查元素类型,泛型擦除后无法保证安全List<Integer>[] arr = new List<Integer>[2];
不能继承 Throwable异常处理需运行时类型信息,泛型擦除后无法匹配class MyException<T> extends Exception { ... }
不能重载擦除后签名相同的方法擦除后方法签名一致,编译器无法区分public void print(List<String> s) {} public void print(List<Integer> i) {}

七、问题与练习:巩固泛型知识

1. 基础问题解答

问题1:编写泛型方法,计算集合中符合特定属性的元素数量(如奇数、素数)。

解答:传入 Predicate<T> 接口(函数式接口),灵活指定属性:

import java.util.Collection;
import java.util.function.Predicate;
public class GenericCounter
{
public static <
T> int countMatching(Collection<
T> coll, Predicate<
T> predicate) {
int count = 0;
for (T elem : coll) {
if (predicate.test(elem)) {
count++;
}
}
return count;
}
public static void main(String[] args) {
Collection<
Integer> nums = Arrays.asList(1, 2, 3, 4, 5);
// 统计奇数(Predicate用Lambda表达式)
int oddCount = countMatching(nums, n -> n % 2 != 0);
System.out.println("奇数数量:" + oddCount);
// 输出3
}
}
问题2:Algorithm 类的 max 方法能否编译?为什么?
public final class Algorithm
{
public static <
T> T max(T x, T y) {
return x > y ? x : y;
}
}

解答:不能编译。T 是无界类型参数,默认是 Object 类型,Object 没有 > 运算符(仅原始类型支持),需添加边界 T extends Comparable<T>,用 compareTo 方法比较。

问题3:Singleton<T> 类能否编译?为什么?
public class Singleton
<
T> {
public static T getInstance() {
if (instance == null)
instance = new Singleton<
T>();
return instance;
}
private static T instance = null;
}

解答:不能编译。静态字段 instance 属于类,而 T 是实例级别的类型参数,静态上下文无法访问实例类型参数,需移除泛型或调整设计(如用静态内部类)。

2. 动手练习:泛型方法交换数组元素

需求:编写泛型方法,交换数组中两个索引处的元素,支持任意类型数组。
实现

public class ArraySwapper
{
public static <
T> void swap(T[] arr, int i, int j) {
if (arr == null || i <
0 || j <
0 || i >= arr.length || j >= arr.length) {
throw new IllegalArgumentException("无效参数");
}
T temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
public static void main(String[] args) {
Integer[] intArr = {
1, 2, 3
};
swap(intArr, 0, 2);
System.out.println(Arrays.toString(intArr));
// 输出[3, 2, 1]
String[] strArr = {
"a", "b", "c"
};
swap(strArr, 1, 2);
System.out.println(Arrays.toString(strArr));
// 输出[a, c, b]
}
}

八、总结:泛型是 Java 类型安全的“基石”

泛型通过“参数化类型”将类型错误从运行时提前到编译时,同时消除冗余的强制转换,让通用算法可安全复用在不同类型上。核心要点:

  1. 泛型类型:定义泛型类/接口,用 <T> 声明类型参数,实例化时用菱形语法简化;
  2. 泛型方法:类型参数声明在返回值前,支持类型推断和边界约束,实现通用逻辑;
  3. 通配符:上界(? extends T)用于输入,下界(? super T)用于输出,灵活处理泛型子类型;
  4. 类型擦除:编译时替换类型参数为边界或 Object,生成桥接方法保持多态;
  5. 限制规避:理解泛型的限制原因,避免实例化类型参数、静态类型字段等错误。

掌握泛型是学好 Java 集合框架、Spring 等框架的前提,也是编写类型安全、高复用代码的关键。后续学习集合(如 ArrayList<T>HashMap<K,V>)时,泛型的知识将帮助你更深刻理解其设计原理。

相关文章:

深入解析:第 9 篇:深入浅出学 Java 语言(JDK8 版)—— 吃透泛型机制,筑牢 Java 类型安全防线

深入解析:第 9 篇:深入浅出学 Java 语言(JDK8 版)—— 吃透泛型机制,筑牢 Java 类型安全防线pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Mon…...

鸿蒙应用开发从入门到实战(八):ArkTS自定义组件语法

ArkUI除系统预置的组件外,还支持自定义组件。使用自定义组件,可使代码的结构更加清晰,并且能提高代码的复用性。**大家好,我是潘Sir,持续分享IT技术,帮你少走弯路。《鸿蒙应用开发从入门到项目实战》系列文章持续更新中,陆续更新AI+编程、企业级项目实战等原创内容、欢迎…...

剑指offer-31、整数中1出现的次数

题⽬描述 求出 1~13 的整数中1出现的次数,并算出 100~1300 的整数中 1 出现的次数?为此他特别数了⼀下 1~13 中包含 1 的数字有 1、10、11、12、13 因此共出现 6 次,但是对于后⾯问题他就没辙了。 ACMer 希望你们帮帮他,并把问题更加普遍化,可以很快的求出任意⾮负整数区间…...

动态黑名单的运作机制与实时防护策略

在数字化浪潮席卷全球的今天,移动应用已成为我们生活与工作的核心载体。然而,繁荣的背后,黑灰产的阴影如影随形。 群控设备批量注册、模拟器多开脚本薅羊毛、自动化程序模拟用户行为进行欺诈引流等等。这些攻击手段日益规模化、专业化、隐蔽化,给企业带来了巨大的经济损失和…...

【译】让性能民主化:Copilot Profiler Agent 在实际代码中的应用

我们很高兴地宣布,Copilot Profiler Agent 已在 Visual Studio 2026 Insider 中推出,它是一款直接内置在 Visual Studio 中的人工智能性能助手。无需再盯着没完没了的调用树或一长串令人费解的数字,疑惑着“我该从哪里开始呢?”—— Copilot Profiler Agent 将改变这一状况…...

JS对象池

s...

objectarx项目props文件中判断条件的修改

为了实现多版本编译, 修改了配置名称, 在原有的debug和release后面增加了版本号后缀, 修改后需要修改props文件中的内容, 否则助兴表无法正常导入, 造成项目无法正常编译。 原有的类似如下:<ImportGroup Label="PropertySheets"><Import Condition=&q…...

效率翻倍新技能:JDK8后的新特性

以下是 JDK 8 至 JDK 21 中最具实用性的新特性整理,涵盖语言特性、工具类增强、性能优化等方向,附代码示例和注释说明: 一、JDK 8(2014):函数式编程与现代化API JDK 8 是 Java 发展的里程碑版本,引入了大量颠覆性特性,至今仍是企业级项目的基础。Lambda 表达式简化匿名…...

实用指南:《URP管线中后处理效果的创新应用与优化实践》

实用指南:《URP管线中后处理效果的创新应用与优化实践》pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", mo…...

百日筑基

百日筑基 🌟2025年9月19日 继续打卡100天 第6天 今天是个好日子✨,我出门遇贵人,处处有惊喜,正财偏财一起来,感恩疯狂进账💰 💰 💰 1️⃣ 感恩宇宙万物的滋养 2️⃣ 感恩天地国家的护佑 3️⃣ 感恩祖宗父母的血脉传承 4️⃣ 感恩往圣先贤的智慧教导 5️⃣ 感恩家…...

顶尖科技人才超50万城市:印度4个,中国3个,美国0个

微信视频号:sph0RgSyDYV47z6快手号:4874645212抖音号:dy0so323fq2w小红书号:95619019828B站1:UID:3546863642871878B站2:UID: 3546955410049087 “9月发布的‘世界百强创新集群排名’中,以深圳为核心的‘深圳-香港-广州’集群结束‘五年老二’地位,超越日本‘东京-横…...

院士增选有效候选人公示材料都有什么内容?

微信视频号:sph0RgSyDYV47z6快手号:4874645212抖音号:dy0so323fq2w小红书号:95619019828B站1:UID:3546863642871878B站2:UID: 35469554100490872025年科学院和工程院增选有效候选人材料公示好多天了,本来想好好学习一下,奈何有的想看的还是看不到,因为很多材料都只在内…...

GPU微架构与多线程架构深入解析

微信视频号:sph0RgSyDYV47z6快手号:4874645212抖音号:dy0so323fq2w小红书号:95619019828B站1:UID:3546863642871878B站2:UID: 3546955410049087 摘要本文深入探讨GPU微架构的核心概念,重点分析多线程架构、存储体冲突、流水线设计以及全局内存合并等关键技术。内容涵盖G…...

TechInsights 拆解:蔚来“亚当(Adam)”超级计算机

微信视频号:sph0RgSyDYV47z6快手号:4874645212抖音号:dy0so323fq2w小红书号:95619019828B站1:UID:3546863642871878B站2:UID: 3546955410049087 添加图片注释,不超过 140 字(可选)蔚来亚当超级计算机是蔚来电动汽车汽车功能的中心。来源:TechInsights汽车制造商正经历…...

拼接

叠甲:作者本人没有 npy,故事纯虚构。谢谢你的陪伴呢!你真的是一个出色的人!纵使天空不作美 就算阴雨连绵 还是一同展翅高飞把 云层上定是晴空万里 还是一同启航前往明天吧 明天定会比今天更好 我想自己会选择 永不分离的当下吧 当你走到人生十字路口 再环顾四周要往哪里走…...

用户只需要知道「怎么办」,不需要知道「为什么炸了」

大家好,我是晓凡。 写在前面 一到月初或者月末(某些业务操作大规模爆发的时候),手机狂震,生产告警狂轰滥炸:xxx接口超时、用户中心 CPU 飙到 98%…… 运维在群里疯狂 @ 你,你却只能回一句“我本地是好的”。 别问,问就是接口设计欠下的技术债。 下面,晓凡总结成 18 条…...

2025数学院士增选背后的争议:海外光环与本土贡献的考量

微信视频号:sph0RgSyDYV47z6快手号:4874645212抖音号:dy0so323fq2w小红书号:95619019828B站1:UID:3546863642871878B站2:UID: 3546955410049087自从2025年中国科学院数学物理学部院士增选有效候选人名单公布以来,学术圈内外的讨论持续升温。一股不同寻常的舆论浪潮在网络…...

完整教程:建筑物裂缝、钢筋裸漏、建筑物墙面脱落图像数据集

完整教程:建筑物裂缝、钢筋裸漏、建筑物墙面脱落图像数据集pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New",…...

深入剖析布谷网剧短剧app系统软件源码之技术

随着短视频和网剧市场的迅猛发展,企业和内容创作者对专业、高效的短剧平台需求日益增长。山东布谷鸟网络科技有限公司凭借丰富的软件开发经验,推出了布谷短剧app源码、网剧系统源码及短剧软件搭建服务,致力于为客户打造一站式数字内容解决方案。 一、布谷短剧app源码简介 布…...

在AI技术快速实现功能的时代,挖掘电子书阅读器新需求成为关键突破点

随着AI技术让功能实现变得前所未有的简单,真正的挑战转向了如何发现和满足用户未被满足的需求。本文通过分析某知名跨平台电子书阅读器的用户反馈,揭示了阅读体验优化、格式兼容性、安全增强等关键需求领域。内容描述 该项目是一个极简主义的跨平台电子书阅读器,基于Tauri框…...

PHP 如何利用 Opcache 来实现保护源码

PHP 如何利用 Opcache 来实现保护源码感兴趣得可以试试看!!!要求不用 IonCube(或类似的)。不知道这是啥的话,就是加密 PHP 代码但还能运行的工具。问题是太贵了。😅 性能要好,PHP 原生支持。原文链接 PHP 如何利用 Opcache 来实现保护源码 后来想到,PHP 有个"op…...

给RAG打分:小白也能懂的AI系统评测全攻略

RAG系统评估听起来高深,其实跟我们生活中的尝鲜评测没啥两样!本文用轻松幽默的方式,带你从检索质量、生成质量到用户体验,全方位掌握如何科学评测RAG系统,避免踩坑,让你的AI应用又快又准。#RAG技术 #AI评估 #信息检索 #大模型 #数据科学你是不是经常被这些问题困扰: &qu…...

P8114 [Cnoi2021] 六边形战士

传送 非常好玩的题! 首先你大概率看过一些“无字证明”,其中很经典的是这个: 证明:用若干个边长为 \(1\),顶角为 \(60\) 度的菱形拼成一个边长为 \(n\) 的正六边形,三个方向的菱形个数一定相等。这是一个经典的无字证明,虽然前置的说明要费很大功夫,不过你不关心这个。…...

【GitHub每日速递 250918】开发者必藏!336k 星标项目告诉你:前端 / 后端 / AI 岗该怎么学才高效

原文:https://mp.weixin.qq.com/s/Oo5T6g68BNe9QUTL4bHrIg AI外语学习神器Enjoy上线!网页版、桌面版全攻略来袭 everyone-can-use-english 是一个帮助用户学习和使用英语的工具类应用。简单讲,它通过技术手段降低英语使用门槛,让每个人都能轻松练习和掌握英语。适用人群:英…...

css-4

定位布局...

【操作系统】从实模式到保护模式,

实模式...

Flutter CSV导入导出:大数据处理与用户体验优化

Flutter CSV导入导出:大数据处理与用户体验优化本文基于BeeCount(蜜蜂记账)项目的实际开发经验,深入探讨如何在Flutter应用中实现高效、用户友好的CSV数据导入导出功能。项目背景 BeeCount(蜜蜂记账)是一款开源、简洁、无广告的个人记账应用。所有财务数据完全由用户掌控,支…...

读人形机器人15未来城市

读人形机器人15未来城市1. 将机器人技术融入城市规划 1.1. 新一轮工业革命的曙光要求我们重新审视城市的设计与功能 1.2. 将机器人技术融入城市规划已不再是未来主义的概念,而是一种现实需要 1.3. 将机器人技术融入城市规划,能够将城市转变为充满活力的智能生态系统1.3.1. 通…...

解锁智能检索新境界:CriticGPT 赋能检索模型洞察人类偏好

随着大型语言模型技术的快速发展,检索增强生成 (RAG) 系统已成为连接海量知识与精准回答的关键桥梁。然而,传统 RAG 模型在理解和满足用户真实需求方面仍存在明显局限。2024 年 6 月 OpenAI 发布的 CriticGPT 技术,为突破这一瓶颈提供了全新思路。本文将深入剖析 Reward-RAG…...

NET 中 Async/Await 的演进:从状态机到运行时优化的 Continuation

NET 中 Async/Await 的演进:从状态机到运行时优化的 Continuation C# 的 `async/await` 长期以来是编写简洁、非阻塞代码的基石,但其传统实现——每个异步方法生成一个独立状态机——在高性能场景(如递归或链式异步调用)中暴露出显著局限性。2025 年的 .NET 9 和 .NET 10 …...

最长公共子序列

题目描述 给你一个序列X和另一个序列Z,当Z中的所有元素都在X中存在,并且在X中的下标顺序是严格递增的,那么就把Z叫做X的子序列。 例如:Z=是序列X=的一个子序列,Z中的元素在X中的下标序列为<1,2,4,6>。 现给你两个序列X和Y,请问它们的最长公共子序列的长度是多少? …...

使用 Ansible 管理服务器集群

Inventory Ansible 使用 /etc/ansible/hosts 管理受控服务器列表: --- ungrouped:hosts:node-1:ansible_host: 192.168.1.1ansible_user: johnnode-2:ansible_host: 192.168.1.2ansible_user: janenode-3:ansible_host: 192.168.1.3ansible_user: frank关于 inventory 文件的字…...

1现在处于非常破防的阶段,不知道为什么会打成这个样子。 ABC 过得很快。看到 D1 的第一眼就会了,发现转移只需要随便优化一下就能通过 D2,不太想写。E 看上去挺可做,F 看上去是板子题。于是开始写 F,不知道这种代码不长、没有任何思维难度的题怎么能写那么长时间,根本原因…...

Codeforces Round 1051 (Div. 2)

A. All Lengths Subtraction 题意:一个排列,对于每个\(k \in [1, n]\),你都要选择一个长度为\(k\)的子数组使得它们都减一,求有没有方案使得最终所有数都是\(0\)。 考虑\(k\)从大到小,发现做\(n\)的时候\(1\)变成\(0\),此时如果\(1\)不在两端,则\(k = n - 1\)时必然再把…...

再不学就晚了!RDT LeRobot与RDKS100部署详解

作者:SkyXZ CSDN:SkyXZ~-CSDN博客 博客园:SkyXZ - 博客园 机械臂:LeRobot-SO101 数采机:MacBook-Pro Python3.10 开发机:Ubuntu 22.04, Cuda12.4,8 NVIDIA A100-SXM4-40GB 开发板:RDK OS 4.0.2 Based on Ubuntu 22.04, Python 3.10.12, OpenExplore 3.2.0 相…...

编译Unity4.3.1f1

参考: 编译 Unity 4.3.1 引擎_unity-source-4.3.1f1-CSDN博客 Unity 4.3.1f1编译调试 - 知乎 Unity source 4.3.1f1 源代码分析-腾讯游戏学堂 附: 早期版本下载(4.x之前的版本)...

【R课堂-电机专栏】为什么提高电机的电压时,转速会随之上升?

本文探讨的问题是 “为什么提高电机的电压时,转速会随之上升?”具体而言,就是当给电机绕组施加的电压升高(增大)时,为什么其转速会随之上升。这一现象看似理所当然,但其背后的原理却涉及诸多物理公式。这个问题对于深入了解电机原理非常关键,下面将为大家详细阐述。●问…...

抽象 CF

一道题在 CF 上有三倍经验,我有个细节假了: \(n \le 10^5\),84 个点的那道在 #64 寄了。 \(n \le 2 \times 10^5\),88 个点的那道在 #88 寄了。 \(n \le 5 \times 10^5\),111 个点的那道直接 A 了。...

单元测试之Mockito使用

测试中为什么需要Mock 在实际的测试中,被测试的对象并不都是可以通过简单的new操作符就可以创建出来的! 实际的业务代码中,一个业务类往往要依赖很多其他的类才能完成一个完整的业务方法,这些依赖包括第三方的rpc,db的查询等等,具体的拓扑如下图我们想测试ClassA,但是Cl…...

Jetson有Jtop,Linux有Htop,RDK也有Dtop!

作者:SkyXZ CSDN:SkyXZ~-CSDN博客 博客园:SkyXZ - 博客园 本项目基于btop开源项目进行二次开发,旨在为RDK平台提供更强大的系统监控工具。 Linux系统下有Htop可以作为系统监控,英伟达的Jetson也有第三方的Jtop,咱们RDK虽然也提供了hrut_somstatus来查看BPU的使用…...

《原子习惯》-读书笔记4

2025.09.17 Day4 1、 养成习惯的过程可以分为四个简单的步骤:提示、渴求、反应和奖励。2、你的头脑在不断分析你的内外部环境,寻找奖励所在的线索。因为线索是我们已然接近奖励的第一个迹象,它自然会导致人们滋生渴求。3、提示的作用是让你注意到奖励的存在。渴求是想要得到…...

Java学习第二天

数据类型 Java、c++是一种强类型语言要求变量的使用要严格符合规定,所有变量都必须先定义后才能使用,安全性高,速度较慢 弱类型语言:安全性低,速度较快 Java数据类型分为两大类:基本类型、引用类型位:计算机内部数据存储的最小单位,11001100是一个八位二进制数 字节:是…...

Java学习第三天

顺序结构 package Scanner;import java.util.Scanner;public class Demo05 {public static void main(String[] args) {//我们可以输入多个数字,并求其总和与平均数,每输入一个数字用回车确认,通过输入非数字来结束输入并非输出执行结果Scanner scanner=new Scanner(System.…...

Java学习第四天

break continue break在任何循环语句的主体部分,均可用break控制循环的流程。break用于强行退出循环,不执行循环中剩余的语句(break语句也在switch语句中使用) continue语句用在循环语句体中,用于终止某次循环过程,即跳过循环体中尚未执行的语句,接着进行下一次是否执行…...

搜索百科(1):Lucene —— 打开现代搜索世界的第一扇门

大家好,我是 INFINI Labs 的石阳。 这是《搜索百科》专栏系列文章,每天 5 分钟,带你速览一款搜索相关的技术或产品,同时还会带你探索它们背后的技术原理、发展故事及上手体验等。 搜索技术看似专业,但它早已深度融入我们的日常生活。无论是电商搜索、知识检索,还是 AI 语…...

02020308 .NET Core核心基础组件08-结构化日志和集中日志服务

02020308 .NET Core核心基础组件08-结构化日志和集中日志服务...

zookeeper的配置

问题:1.1号和二号虚拟机可以成功启动三号报错 2025-09-17 17:57:46,219 [myid:] - INFO [main:QuorumPeerConfig@133] - Reading configuration from: /export/server/apache-zookeeper-3.5.6-bin/bin/../conf/zoo.cfg 2025-09-17 17:57:46,228 [myid:] - INFO [main:Quorum…...

02020307 .NET Core核心基础组件07-什么是Logging、NLog

02020307 .NET Core核心基础组件07-什么是Logging、NLog...

算法第一周博客

算法第一周博客任务一,搜索大公司内部编码规范,列出本学期编码需遵守的规范 1.程序块要采用缩进风格编写,缩进的空格数为4个,使得层次分明。 2.控制每行最大长度不超120个字符,超过时换行并适当缩进,并且一行通常一个语句。 3.命名标识符(包括变量,函数,结构体等)时,…...

nid修改dbid/dbname

Table of Contents1. 简述 2. 操作步骤说明 3. 操作命令1. 简述2. 操作步骤说明如果配置了DBconsole,需要删除DBconsole对象。之后完全关闭,再启动到mount状态。 nid 命令支持修改dbid 和 dbname两个值。具体操作见之后示例。 但是在操作之前,需要明确是只需要修改dbid 还是同…...