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

刚刚 Java 25 炸裂发布!让 Java 再次伟大

大家好,我是程序员鱼皮。

刚刚,Java 25 正式发布!这是继 Java 21 之后,又一个 LTS 长期支持版本,也是 Java 开发者们最期待的版本之一。其中有个特性可以说是颠覆了我对 Java 的认知,让 Java 再次伟大!

那么 Java 25 都发布了哪些新特性?有没有必要升级?

一篇文章,带你速通 Java 新特性,学会后又能愉快地和面试官吹牛皮了~

推荐观看视频版:https://bilibili.com/video/BV1b5pCzGEPx

⭐️ 正式特性

这些特性在 Java 25 中正式稳定,可以在生产环境中放心使用。

【实用】Scoped Values 作用域值

如果我问你:怎么在同一个线程内共享数据?

估计你的答案是 ThreadLocal。

但是你有没有想过,ThreadLocal 存在什么问题?

举一个典型的 ThreadLocal 使用场景,在同一个请求内获取用户信息:

public class UserService {
   private static final ThreadLocal<StringUSER_ID new ThreadLocal<>();
   
   public void processRequest(String userId) {
       USER_ID.set(userId);  // 写入
       doWork();
       USER_ID.remove();  // 问题:必须手动清理,容易忘记
  }
   
   public void doWork() {
       String userId USER_ID.get();  // 读取
       System.out.println("处理用户: " userId);
       // 问题:其他代码可以随意修改
       USER_ID.set("被篡改的值");
  }
}

这段简单的代码其实暗藏玄鸡,可以看出 ThreadLocal 的痛点:

  1. 容易内存泄漏:必须手动调用 remove()

  2. 可以随意修改数据,可能导致不可预期的结果

此外,如果想让子线程也共享数据,每个子线程都要复制一份数据。如果你使用的是 Java 21 的虚拟线程,1000 个虚拟线程就要复制1000 次,性能很差。

InheritableThreadLocal<StringthreadLocal new InheritableThreadLocal<>();
threadLocal.set("用户数据");
for (int 0; 1000; i++) {
   Thread.ofVirtual().start(() -> {
       String data threadLocal.get(); // 每个线程都有自己的副本
  });
}

现在 Java 25 的 Scoped Values 特性转正了,能解决 ThreadLocal 的这些问题。

 

什么是 Scoped Values?

Scoped Values 允许方法 在线程内以及子线程间安全高效地共享不可变数据

和传统的 ThreadLocal 相比,它不仅更安全,而且在虚拟线程环境下的内存开销要小很多。

Scoped Values 和 ThreadLocal 的写法很像:

import static java.lang.ScopedValue.where;

public class UserService {
   private static final ScopedValue<StringUSER_ID ScopedValue.newInstance();
   
   public void processRequest(String userId) {
       where(USER_ID, userId)  // 写入并绑定作用域
          .run(this::doWork);
       // 自动清理,无需 remove()
  }
   
   public void doWork() {
       String userId USER_ID.get();  // 读取
       System.out.println("处理用户: " userId);
  }
}

这段代码中,我们使用 where().run() 自动管理作用域,出了作用域就自动清理,更安全。

而且作用域一旦绑定,值就不能被修改,避免意外的状态变更。

和虚拟线程配合使用时,所有虚拟线程共享同一份数据,内存占用更小:

ScopedValue<StringscopedValue ScopedValue.newInstance();
where(scopedValue, "用户数据").run(() -> {
   for (int 0; 1000; i++) {
       Thread.ofVirtual().start(() -> {
           String data scopedValue.get(); // 所有线程共享同一份数据
      });
  }
});

 

使用方法

1)支持返回值

除了 run() 方法,还可以使用 call() 方法来处理有返回值的场景:

public String processWithResult(String input) {
   return where(CONTEXT, input)
      .call(() -> {
           String processed doSomeWork();
           return "结果: " processed;
      });
}

 

2)嵌套作用域

支持在已有作用域内建立新的嵌套作用域:

void outerMethod() {
   where(X, "hello").run(() -> {
       System.out.println(X.get());  // 输出 "hello"
       where(X, "goodbye").run(() -> {
           System.out.println(X.get());  // 输出 "goodbye"
      });
       System.out.println(X.get());  // 输出 "hello"
  });
}

 

3)多值绑定

可以在一个调用中绑定多个 Scoped Values,或者直接用类封装多个值:

where(USER_ID, userId)
  .where(REQUEST_ID, requestId)
  .where(TENANT_ID, tenantId)
  .run(() -> {
       processRequest();
  });

 

4)和结构化并发配合

Scoped Values 和 Java 结构化并发 API 可以打个配合,子线程自动继承父线程的作用域值:

void handleRequest() {
   where(USER_ID, getCurrentUserId())
      .run(() -> {
           try (var scope new StructuredTaskScope.ShutdownOnFailure()) {
               var userTask scope.fork(() -> loadUser());      // 子线程可以访问 USER_ID
               var ordersTask scope.fork(() -> loadOrders());  // 子线程可以访问 USER_ID
               scope.join().throwIfFailed();
               return new Response(userTask.get(), ordersTask.get());
          }
      });
}

不过结构化并发这哥们也挺惨的,过了这么多个版本还没转正。等它转正了,感觉 Java 并发编程的模式也要改变了。

 

使用场景

虽然 Scoped Values 听起来比 ThreadLocal 更高级,但它不能 100% 替代 ThreadLocal。

如果你要在线程中共享不可变数据、尤其是使用了虚拟线程的场景,建议使用 Scoped Values;但如果线程中共享的数据可能需要更新,那么还是使用 ThreadLocal,要根据实际场景选择。

 

【实用】模块导入声明

模块导入声明特性(Module Import Declarations)虽然是首次亮相,但它的设计理念可以追溯到 Java 9 的模块系统。

模块系统允许我们将代码组织成模块,每个模块都有明确的依赖关系和导出接口,让大型应用的架构变得更加清晰和可维护。

模块导入声明是在这个基础上进一步简化开发体验。

以前我们使用多个 Java 标准库的包需要大量的导入语句:

import java.util.Map;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import java.util.function.Function;
import java.nio.file.Path;
import java.nio.file.Files;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
// ... 还有更多

 

现在可以一行导入整个模块:

import module java.base;

 

对于聚合模块(比如 java.se),一次导入可以使用大量包:

import module java.se;  // 导入 100 多个包

public class FullFeatureApp {
   // 可以使用整个 Java SE 平台的所有公开 API
}

 

不过我感觉这个特性会比较有争议,我记得大厂的 Java 规约中是禁止使用通配符 * 方式导入所有类的,可读性差、有命名冲突风险、依赖不明确。

而模块导入的范围更大,类名冲突可能更严重。如果导入多个模块时遇到了同名类,还要再通过具体导入来解决:

import module java.base;      // 包括 java.util.List 接口
import module java.desktop;   // 包括 java.awt.List 类

import java.util.List;        // 明确指定使用 util 包的 List

所以我可能不会用这个特性,纯个人偏好。

 

【必备】紧凑源文件和实例主方法

这是我最喜欢的特性,直接打破了外界对于 Java 的刻板印象!

之前不是都说 Java 入门比 Python 难么?一个简单的 Hello World 程序就要包含类、public、static、方法参数等概念。

传统的 Hello World 程序:

public class HelloWorld {
   public static void main(String[] args) {
       System.out.println("Hello, World!");
  }
}

用 Python 或者 JavaScript 直接写一行代码就完成了:

print("Hello World")

在 Java 25 中,Hello World 程序可以直接简写为 3 行代码!

void main() {
   IO.println("Hello, World!");
}

这么一看和好多语言都有点像啊。。。安能辨我是 Java?

但是你知道,这 3 含代码的含金量么?你知道 Java 为了支持简写成这 3 行代码付出了多少努力么?

 

新的 IO 类

首先是 Java 25 在 java.lang 包中新增了 IO 类,提供更简单的控制台 I/O 操作:

void main() {
   String name IO.readln("请输入您的姓名: ");
   IO.print("很高兴认识您,");
   IO.println(name);
}

 

IO 类的主要方法包括:

public static void print(Object obj);
public static void println(Object obj);
public static void println();
public static String readln(String prompt);
public static String readln();

 

自动导入 java.base 模块

在紧凑源文件中,所有 java.base 模块导出的包都会自动导入,就像有这样一行代码:

import module java.base;

也就是说,你可以直接使用 List、Map、Stream 等常用类:

void main() {
   var fruits List.of("苹果", "香蕉", "橙子");
   var lengths fruits.stream()
      .collect(Collectors.toMap(
           fruit -> fruit,
           String::length
      ));
   IO.println("水果及其长度: " lengths);
}

这样一来,Java 对初学者更友好,同时也让有经验的开发者能快速编写脚本和小工具。

我觉得这个特性是让 Java 再次伟大的关键,为什么呢?

Java 的核心竞争优势在于它成熟完善的生态系统,但语法不够简洁;现在 Java 只要持续借鉴其他新兴编程语言的优秀设计和语法特性、给开发者提供平滑的技术升级路径,就还是会有很多开发者继续使用 Java,就不会被别的语言取代。

 

【实用】灵活的构造函数体

这个特性解决的是 Java 自诞生以来就存在的一个限制:构造函数中的 super()this() 调用必须是第一条语句。

这个限制虽然保证了对象初始化的安全性,但可能也会影响我们的编码。

举个例子:

class Employee extends Person {
   Employee(String name, int age) {
       super(name, age);  // 必须是第一条语句
       if (age 18 || age 67) {
           throw new IllegalArgumentException("员工年龄不符要求");
      }
  }
}

这种写法的问题是,即使参数不符合要求,也会先调用父类构造函数,做一些可能不必要的工作。

Java 25 打破了这个限制,引入了新的构造函数执行模型,分为两个阶段:

  1. 序言阶段:构造函数调用之前的代码

  2. 尾声阶段:构造函数调用之后的代码

简单来说,允许在构造函数调用之前添加语句!

class Employee extends Person {
   String department;
   
   Employee(String name, int age, String department) {
       // 序言阶段,可以校验参数
       if (age 18 || age 67) {
           throw new IllegalArgumentException("员工年龄必须在 18-67 之间");
      }        
       // 可以初始化字段
       this.department department;
       // 验证通过后,再调用父类构造函数
       super(name, age);
       // 尾声阶段,可以干点儿别的事
       IO.println("新员工 " name " 已加入 " department " 部门");
  }
}

怎么样,感觉是不是一直以来背的八股文、做的选择题崩塌了!

此外,这个特性还能防止父类构造函数调用子类未初始化的方法:

class Base {
   Base() {
       this.show();  // 调用可能被重写的方法
  }
   void show() {
       IO.println("Base.show()");
  }
}

class Yupi extends Base {
   private String message;
   
   Yupi(String message) {
       this.message message;  // 在 super() 之前初始化
       super();
  }
   
   @Override
   void show() {
       IO.println("消息: " message);  // message 已经正确初始化了
  }
}

现在,当创建 Yupi 对象时,message 字段会在父类构造函数运行之前就被正确初始化,避免了打印 null 值的问题。

 

限制条件

但是要注意,在序言阶段有一些限制:

  1. 不能使用 this 引用(除了字段赋值)

  2. 不能调用实例方法

  3. 只能对未初始化的字段进行赋值

class Example {
   int value;
   String name "default";  // 有初始化器
   
   Example(int val, String nm) {
       // ✅ 允许:验证参数
       if (val 0) throw new IllegalArgumentException();
       
       // ✅ 允许:初始化未初始化的字段
       this.value val;
       
       // ❌ 不允许:字段已有初始化器
       // this.name = nm;
       
       // ❌ 不允许:调用实例方法
       // this.helper();
       
       super();
       
       // ✅ 现在可以正常使用 this 了
       this.name nm;
       this.helper();
  }
   
   void helper() { /* ... */ }
}

总之,这个特性让构造函数变得更加灵活和安全,特别适合需要复杂初始化逻辑的场景。

 

【了解】密钥派生函数 API

随着量子计算技术的发展,传统的密码学算法面临威胁,后量子密码学成为必然趋势。

因此 Java 也顺应时代,推出了密钥派生函数(KDF),这是一种从初始密钥材料、盐值等输入生成新密钥的加密算法。

简单来说,你理解为 Java 出了一个新的加密工具类就好了,适用于对密码进行加强、从主密钥派生多个子密钥的场景。

核心是 javax.crypto.KDF 类,提供了两个主要方法:

  1. deriveKey() 生成 SecretKey 对象

  2. deriveData() 生成字节数组

比如使用 HKDF(HMAC-based Key Derivation Function)算法:

// 创建 HKDF 实例
KDF hkdf KDF.getInstance("HKDF-SHA256");

// 准备初始密钥材料和盐值
byte[] initialKeyMaterial "my-secret-key".getBytes();
byte[] salt "random-salt".getBytes();
byte[] info "application-context".getBytes();

// 创建 HKDF 参数
AlgorithmParameterSpec params HKDFParameterSpec.ofExtract()
  .addIKM(initialKeyMaterial)  // 添加初始密钥材料
  .addSalt(salt)               // 添加盐值
  .thenExpand(info, 32);       // 扩展为 32 字节

// 派生 AES 密钥
SecretKey aesKey hkdf.deriveKey("AES", params);

// 或者直接获取字节数据
byte[] derivedData hkdf.deriveData(params);

 

【了解】紧凑对象头

了解过 Java 对象结构的同学应该知道,Java 对象除了存储数据外,还要通过 对象头 存储很多额外的信息,比如类型信息、GC 标记、锁状态等元数据。

 

如果程序中要创建大量小对象,可能对象头本身占用的空间都比实际要存储的数据多了!

比如下面这段代码:

class Point {
   int x, y;  // 实际数据只有 8 字节
}

// 创建一堆 Point 对象
List<Pointpoints new ArrayList<>();
for (int 0; 10000; i++) {
   points.add(new Point(i, i));  // 每个对象实际占用 24 字节!
}

用来存储传统的对象头在 64 位系统上占 16 字节,对于只有 8 字节数据的 Point 来说,开销确实有点大。

Java 25 将紧凑对象头特性转正,把对象头从 16 字节压缩到 8 字节,减少了小对象的内存开销。

但是,紧凑对象头并不是默认开启的,需要手动指定。毕竟少存了一些信息,必须考虑到兼容性,比如下面这几种情况可能会有问题:

  • 使用了 JNI 直接操作对象头的代码

  • 依赖特定对象头布局的调试工具

  • 某些第三方性能分析工具

 

【了解】Shenandoah 分代收集

对于 Java 这种自动垃圾收集的语言,我们经常遇到这种问题:GC 一运行,应用就卡顿。特别是占用大堆内存的应用,传统的垃圾收集器一跑起来,停顿时间可能多达几百毫秒甚至几秒。

Shenandoah 作为 Java 中延迟最低的垃圾收集器,在 Java 25 中 Shenandoah 的分代模式转为正式特性。

什么是分代垃圾回收呢?

大部分对象都是 “朝生夕死” 的。将堆内存划分为年轻代和老年代两个区域,年轻代的垃圾收集可以更加频繁和高效,因为大部分年轻对象很快就会死亡,收集器可以快速清理掉这些垃圾;而老年代的收集频率相对较低,减少了对长期存活对象的不必要扫描。

经过大量测试,分代 Shenandoah 在保持超低延迟的同时,还能获得更好的吞吐量。对于延迟敏感的应用来说,这个改进还是很实用的。

但是 Shenandoah 并不是默认的垃圾收集器,需要手动指定。而且分代模式也不是 Shenandoah 的默认模式,默认情况下 Shenandoah 还是使用单代模式。

 

预览特性

这些特性仍在预览阶段,可以体验 但不建议在生产环境使用

【了解】结构化并发

目前我们经常使用 ExecutorService 实现并发,可能会写下面这种代码:

// 传统写法
Response handle() throws ExecutionException, InterruptedException {
   Future<Stringuser executor.submit(() -> findUser());
   Future<Integerorder executor.submit(() -> fetchOrder());
   
   String theUser user.get();   // 如果这里异常了
   int theOrder order.get();    // 这个任务还在跑,造成线程泄漏!
   
   return new Response(theUser, theOrder);
}

上述代码存在一个问题,如果 findUser() 方法失败了,fetchOrder() 还在后台运行,浪费资源。而且如果当前线程被中断,子任务不会自动取消。

 

什么是结构化并发?

结构化并发就是来解决并发编程中 线程泄露和资源管理 问题的。它在 Java 25 中第 5 次预览,API 已经成熟,盲猜下个版本就要转正了。

结构化并发的基本使用方法:

Response handle() throws InterruptedException {
   // 打开新作用域,打开作用域的线程是作用域的所有者。
   try (var scope StructuredTaskScope.open()) {
       // 使用 fork 方法在作用域中开启子任务
       var userTask scope.fork(() -> findUser());
       var orderTask scope.fork(() -> fetchOrder());
       // 等待所有子任务完成或失败
       scope.join();
       return new Response(userTask.get(), orderTask.get());
  }
   // 作用域结束时,所有子任务自动清理,不会泄漏
}

这样就解决了几个问题:

  • 自动清理:任一任务失败,其他任务自动取消

  • 异常传播:主线程被中断,子任务也会取消

  • 资源管理:可以配合 try-with-resources 保证资源释放

 

更多用法

Java 25 提供了多种执行策略:

// 1. 默认策略:所有任务都要成功
try (var scope StructuredTaskScope.open()) {
   // 任一失败就全部取消
}

// 2. 竞速策略:任一成功即可
try (var scope StructuredTaskScope.open(Joiner.anySuccessfulResultOrThrow())) {
   var task1 scope.fork(() -> callService1());
   var task2 scope.fork(() -> callService2());
   var task3 scope.fork(() -> callService3());
   
   // 谁先成功就用谁的结果,其他任务取消
   return scope.join();
}

// 3. 收集所有结果(忽略失败)
try (var scope StructuredTaskScope.open(Joiner.awaitAll())) {
   // 等待所有任务完成,不管成功失败
}

结构化并发搭配虚拟线程,可以轻松处理大量并发:

void processLotsOfRequests() throws InterruptedException {
   try (var scope StructuredTaskScope.open()) {
       // 创建上万个虚拟线程都没问题
       for (int 0; 10000; i++) {
           int requestId i;
           scope.fork(() -> processRequest(requestId));
      }
       scope.join();  // 等待所有请求处理完成
  }
   // 自动清理,不用担心线程泄漏
}

 

【了解】基本类型模式匹配

之前 Java 优化过很多次模式匹配,可以利用 switch 和 instanceof 快速进行类型检查和转换。

比如:

public String processMessage(Object message) {
   return switch (message) {
       case String text -> "文本消息:" text;
       case Integer number -> "数字消息:" number;
       case List<?> list -> "列表消息,包含 " list.size() " 个元素";
       case  -> "空消息";
       default -> "未知消息类型";
  };
}

但是目前模式匹配只能用于引用类型,如果你想在 switch 中匹配基本类型,只能用常量,不能绑定变量。

支持基本类型模式匹配后,switch 中可以使用基本类型:

switch (value) {
   case int when 100 -> "大整数: " i;
   case int -> "小整数: " i;
   case float -> "浮点数: " f;
   case double -> "双精度: " d;
}

注意这里的 int i,变量 i 绑定了匹配的值,可以直接使用。

而且基本类型模式会检查转换是否安全,这比手动写范围检查方便多了!

int largeInt 1000000;

// 检查能否安全转换为 byte
if (largeInt instanceof byte b) {
   IO.println("可以安全转换为 byte: " b);
else {
   IO.println("转换为 byte 会丢失精度");  // 这个会执行
}

// 检查 int 转 float 是否会丢失精度
int preciseInt 16777217;  // 2^24 + 1
if (preciseInt instanceof float f) {
   IO.println("转换为 float 不会丢失精度");
else {
   IO.println("转换为 float 会丢失精度");  // 这个会执行
}

 

【了解】Stable Values 稳定值

这个特性对大多数开发者来说应该是没什么用的。

不信我先考考大家:final 字段有什么问题?

答案是必须在构造时初始化。

举个例子:

class OrderController {
   private final Logger logger Logger.create(OrderController.class);
}

这段代码中,logger 必须立刻初始化,如果创建 logger 很耗时,所有实例都要等待,可能影响启动性能。

特别是在对象很多、但不是每个都会用到某个字段的场景下,这种强制初始化就很浪费。

但我又想保证不可变性,怎么办呢?

Stable Values 可以解决上述问题,提供 延迟初始化的不可变性

class OrderController {
   private final StableValue<Loggerlogger StableValue.of();
   
   Logger getLogger() {
       // 只在首次使用时初始化,之后直接返回同一个实例
       return logger.orElseSet(() -> Logger.create(OrderController.class));
  }
}

说白了其实就是包一层。。。

还有更简洁的写法,可以在声明时指定初始化逻辑:

class OrderController {
   private final Supplier<Loggerlogger 
       StableValue.supplier(() -> Logger.create(OrderController.class));
   
   void logOrder() {
       logger.get().info("处理订单");  // 自动延迟初始化
  }
}

还支持集合的延迟初始化:

class ConnectionPool {
   // 延迟创建连接池,每个连接按需创建
   private static final List<Connectionconnections 
       StableValue.list(POOL_SIZE, index -> createConnection(index));
   
   public static Connection getConnection(int index) {
       return connections.get(index);  // 第一次访问才创建这个连接
  }
}

重点是,Stable Values 底层使用 JVM 的 @Stable 注解,享受和 final 字段一样的优化(比如常量折叠),所以不用担心性能。

这个特性特别适合:

  • 创建成本高的对象

  • 不是每个实例都会用到的字段

  • 需要延迟初始化但又要保证不可变的场景

没记错的话这个特性应该是首次亮相,对于追求性能的开发者来说还是挺实用的。

 

其他特性

【了解】移除 32 位 x86 支持

Java 25 正式移除了对 32 位 x86 架构的支持。

简单来说就是:32 位系统现在用不了 Java 25 了。

不过对绝大多数朋友来说,这个变化应该没啥影响。

 

【了解】JFR 性能分析增强

JFR(Java Flight Recorder)飞行记录器是 JDK 内置的低开销性能监控工具,可以记录程序运行时的详细数据。

它在这个版本获得了几个重要增强,包括更精确地测量 CPU 使用情况、通过协作式采样保证了 JVM 安全性、可以更安全地在生产环境开启分析等。

 

【了解】Vector API(第 10 次孵化)

Vector API 继续孵化,主要改进:

  1. 更好的数学函数支持:现在通过 FFM API 调用本地数学库,提高可维护性

  2. Float16 支持增强:在支持的 CPU 上可以自动向量化 16 位浮点运算

  3. VectorShuffle 增强:支持与 MemorySegment 交互

这个 API 对高性能计算、机器学习等领域很重要,尤其是现在 AI 的发展带火了向量运算。但是我想说真的别再孵化了,等你转正了,黄花菜都凉了。

 


 

以上就是 Java 25 的新特性了,不知道大家有什么想法,可以在评论区留言分享。

我的评价是:虽然 Java 25 在开发体验、性能优化和并发编程方面都有进步,雨露均沾,但是目前对于新项目选择 Java 21 就够了,老项目还是可以继续用 Java 8,真没必要升级到 Java 25。

但是建议大家还是把 Java 8 之后的 Java 新特性都了解一下,拓宽下知识面,面试的时候也能跟面试官多聊几句。我也把免费 Java 教程和 Java 新特性大全都整理到编程导航上了:

免费 Java 教程 + 新特性大全:https://codefather.cn/course/java

如果本期内容有收获,记得点赞关注三连支持,我们下期见。

更多编程学习资源

  • Java前端程序员必做项目实战教程+毕设网站

  • 程序员免费编程学习交流社区(自学必备)

  • 程序员保姆级求职写简历指南(找工作必备)

  • 程序员免费面试刷题网站工具(找工作必备)

  • 最新Java零基础入门学习路线 + Java教程

  • 最新Python零基础入门学习路线 + Python教程

  • 最新前端零基础入门学习路线 + 前端教程

  • 最新数据结构和算法零基础入门学习路线 + 算法教程

  • 最新C++零基础入门学习路线、C++教程

  • 最新数据库零基础入门学习路线 + 数据库教程

  • 最新Redis零基础入门学习路线 + Redis教程

  • 最新计算机基础入门学习路线 + 计算机基础教程

  • 最新小程序入门学习路线 + 小程序开发教程

  • 最新SQL零基础入门学习路线 + SQL教程

  • 最新Linux零基础入门学习路线 + Linux教程

  • 最新Git/GitHub零基础入门学习路线 + Git教程

  • 最新操作系统零基础入门学习路线 + 操作系统教程

  • 最新计算机网络零基础入门学习路线 + 计算机网络教程

  • 最新设计模式零基础入门学习路线 + 设计模式教程

  • 最新软件工程零基础入门学习路线 + 软件工程教程

相关文章:

刚刚 Java 25 炸裂发布!让 Java 再次伟大

刚刚,Java 25 正式发布! Java 25 都发布了哪些新特性?有没有必要升级?一篇文章,带你速通 Java 新特性。大家好,我是程序员鱼皮。 刚刚,Java 25 正式发布!这是继 Java 21 之后,又一个 LTS 长期支持版本,也是 Java 开发者们最期待的版本之一。其中有个特性可以说是颠覆…...

go 语言结构和基础语法

结构和语法基础包声明 package main引入包函数init函数 22 会先执行init函数在执行main 函数 -------init------ hello world ------main--------变量标识符行分隔符语句&表达式注释公有成员和私有成员关键词、保留字和预定义标志引用类型切片 map channel interface func关…...

详细介绍:Linux--初识网络

详细介绍:Linux--初识网络pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", monospace !important; font-siz…...

lua程序调试方法

使用腾讯luahelper插件(lua全家桶,其中调试部分应用了LuaPanda实现) 主要有两个功能,一个是附加到已经运行的lua程序上,另一个是用debug方式运行lua程序文件,安装后默认没有配置文件,先add config就好。纯属记录程序人生,如有差错,欢迎指正,轻喷...

维保信息查询

超聚变查看维保信息: https://www.xfusion.com/support/#/zh/maintenance-information...

人工智能学习路线学习资料整理

人工智能学习资料(个人整理) 先导 开始之前,让我们先看几个demo和视频 【纪录片】阿尔法狗【双语特效字幕】 https://www.bilibili.com/video/BV1pE411y7Pu/?spm_id_from=333.337.search-card.all.click&vd_source=d5f2b87dc23c8806dfc6d9550f24aaf2路线 书籍资源—理论…...

软件设计师知识点总结(2023)上

第1题: 第2题: 第3题: 第4题: 第5题: 第6题:第7题:第8题: 第9题: 先来先服务:最短寻道时间:电梯调度: 单向扫描: 第10题: 第11题: 第12题: 第13题: 第14题: 第15题: 第16题: 第17题: 第18题: 第19题:...

【运维自动化-标准运维】各类全局变量使用说明(中)

一、集群资源筛选 此变量用于按照资源筛选方案创建新的集群。 创建 输入名称和KEY值 引用 ${KEY}引用${KEY},返回的是创建集群成功的信息Allocate {set_number} sets with names: 引用${KEY._module},返回的是集群下的模块信息,类型为字典,键为模块名,值为模块下的主机列表…...

提示词工程(Prompt Engineering)是不是“新时代的编程”?

一、引子:为什么大家开始重视 Prompt?从 ChatGPT、Claude 到文生图工具(Stable Diffusion、MidJourney),AI 输出的质量高度依赖输入的提示词。不同的人输入同样的问题,得到的答案可能天差地别。出现了一个新角色:提示词工程师(Prompt Engineer),甚至有公司开出年薪几…...

python日志记录之logging模块

logging模块是python中用于提供格式化输出的模块。...

O - Color a Tree

题意:任务是在一棵树状结构中以最小的成本完成所有节点的染色,如果要染一个节点那么他的父节点必须已经染过色。染色成本取决于节点的染色成本因子与染色时间。通过分析得出正确的染色策略,并给出了一种有效的算法实现。 错误的贪心策略:对于一个节点的子节点 染过这个结点…...

电脑时间改了,软件不能用了

软件突然不能用了,检查没什么问题,重装也查不出来毛病,想再卸载的时候,发现日期改成了几年前。 日期改正软件就好了。。。...

OFDM 自适应功率与比特分配

1. 要点场景:单用户 OFDM,频率选择性衰落,完美 CSI 目标:总功率约束下 最大化速率 或 总速率约束下 最小化功率 算法:注水(Water-Filling)——理论最优 Chow——次优,低复杂度 Hughes-Hartogs——贪婪,最优但慢输出:子载波功率、比特数、BER vs Eb/N0、容量曲线2. 结…...

前 k 小问题期末考

有意思P6646...

1380亿条微博全量数据集,可用于自然语言处理、情感分析、舆情分析、推荐系统、用户行为数据、商业智能、人工智能模型训练、中文文本数据、地理位置信息、时间序列分析、JSON格式、机器学习、文本挖掘等

引言与背景 在数字化时代,社交媒体数据已成为理解人类行为、社会趋势和语言演变的宝贵资源。微博作为中国最大的社交媒体平台之一,汇聚了亿万用户的真实表达,承载着丰富的社会信息和文化内涵。本数据集自2015年开始采集至今,累计收集了约1380亿条微博数据,为人工智能研究、…...

本土化技术平台的崛起:Gitee如何重塑中国开发者生态

本土化技术平台的崛起:Gitee如何重塑中国开发者生态 在数字化转型浪潮席卷全球的当下,中国开发者生态正经历着一场深刻的变革。作为这一变革的重要见证者和推动者,Gitee这一本土代码托管平台凭借其独特的本土化优势,正在重新定义中国开发者的工作方式。最新数据显示,Gitee…...

一次内网穿透的实践

博主还在上学,因为要经常跑一些仿真实验(实验需要在Linux系统下才能跑),而博主手里有两台台式主机: 1)实验室主机(windows系统,性能较弱) 2)宿舍主机(windows系统,性能较强) 但是由于老师经常派活所以本人大部分时间还是位于实验室的,这就导致大部分时间我都是利…...

m1芯片怎么安装windows系统

如何在M1芯片Mac上安装Windows系统 一、M1芯片与Windows系统的兼容性介绍 Apple M1芯片是苹果公司推出的首款专为Mac设计的基于Arm架构的处理器。它集成了CPU、GPU、神经网络引擎等组件,使得Mac电脑在性能、能效等方面有了显著提升。然而,由于M1芯片采用的是Arm架构,而Windo…...

m1оƬװx86windowsϵͳ

如何在M1芯片上安装x86 Windows系统 随着技术的不断进步,苹果公司推出的搭载M1芯片的Mac电脑凭借其出色的性能和能效比受到了广泛欢迎。然而,对于一些需要运行特定Windows应用程序的用户来说,如何在基于ARM架构的M1芯片上安装原本为x86架构设计的Windows系统成为了一个挑战。…...

C++ 强制类型转化

C++ 提供了四种显式强制类型转换运算符(static_cast、dynamic_cast、const_cast、reinterpret_cast),相比 C 风格的强制转换((类型)表达式),它们更具针对性、可读性和安全性,能让转换意图更清晰,且编译器可提供更严格的检查。 1、static_cast - 静态转换 用于编译器可在…...

Linux shred 命令:安全擦除文件指南

Linux shred 命令:安全擦除文件指南Linux 中的 shred 命令是一个用于​​安全删除文件​​的工具,它通过多次覆盖文件内容来确保数据难以恢复,非常适合处理敏感信息。下面我将为你详细解释这个命令的用法、注意事项以及典型应用场景。 🛡️ Linux shred 命令:安全擦除文件…...

研究生化学英文题库数据集:300万条LaTeX格式AI训练资源,覆盖有机化学物理化学无机化学分析化学,用于智能评估系统、个性化学习平台、化学知识图谱构建、自动化工具开发、深度学习模型

引言与背景 在当今人工智能技术飞速发展的时代,专业化学教育领域正面临着前所未有的变革机遇。化学作为一门基础性、应用性极强的学科,其教育质量的提升直接关系到国家科技创新能力和人才培养水平。然而,传统的化学教育模式在个性化学习、智能评估和知识体系构建方面仍存在诸…...

lvm硬盘分区与不分区优缺点

一、不分区,直接用整块硬盘创建 PV pvcreate /dev/sdb vgcreate myvg /dev/sdb 优点:简单快捷,少了一层分区表的管理。硬盘整个容量都能交给 LVM 管理,空间利用最大化。避免分区表损坏导致 LVM 无法识别的问题。缺点:硬盘完全交由 LVM 使用,不能轻易与其他用途(比如放一…...

中电金信能碳虚拟电厂数智化平台破局“双碳”难题

在国家“双碳”目标持续推进的背景下,零碳园区已成为实现碳达峰碳中和(“双碳”)的重要抓手。2023年《国家碳达峰试点建设方案》提出选取100个典型城市和园区试点;2024年中央经济工作会议首次提出建设一批“零碳园区”;2025年3月政府工作报告将“零碳园区”建设纳入年度重…...

充分验证用户需求和商业价值,是软件创业者首要解决的问题

引言 最近常混迹于各类创业和技术圈子,看到很多不错的产品,但痛苦的是,你几乎能预料到他们大部分都会很快陨落,这引起了我的思考。 软件创业的目的 软件创业驱动方式无非三种:一个兴趣驱动、二是使命感或成就感驱动,三是商业驱动。三者虽有不同,但其中有一个目的都是一样…...

国产DevOps工具链崛起:Gitee如何赋能企业数字化转型

国产DevOps工具链崛起:Gitee如何赋能企业数字化转型 在数字化转型的浪潮中,中国企业正面临前所未有的技术升级压力。随着国际形势变化和国内政策导向,构建自主可控的DevOps工具链已成为企业技术决策者的战略选择。Gitee作为国内领先的代码托管与DevOps平台,凭借其本地化服务…...

milvus创建一个用户管理多个库

1.创建用户export CLUSTER_ENDPOINT="http://localhost:19530" export TOKEN="root:Milvus"curl --request POST \ --url "${CLUSTER_ENDPOINT}/v2/vectordb/users/create" \ --header "Authorization: Bearer ${TOKEN}" \ --header &…...

为什么ceph新添加的硬盘会自动变为osd

您好!这是一个非常好的问题,也是 Ceph 运维中一个关键的特性。 根据您图片中的信息和您描述的现象(新硬盘会自动变为 OSD),​​根本原因在于 Ceph 集群(特别是 cephadm)的“自动化运维(Orchestrator)”功能默认是开启的,并且它有一个默认策略:自动识别和利用所有“可…...

Zabbix Proxy 技术实践与运维思考

在分布式监控体系中,Zabbix Proxy 是一个常被忽视但极具价值的组件。相比单点的 Zabbix Server,它更像是一座“前哨站”:在业务网络的前沿收集监控数据、缓存事件,并将结果按需汇聚到中心。本文将结合实际运维案例,深入探讨 Zabbix Proxy 的定位、部署要点与常见问题。 一…...

OF SF CF ZF 的判断方式以及例子

进位/借位标志CF,最高位有进位/错位时CF=1 零标志ZF,运算结果为0时,ZF=1 符号标志SF,运算结果为负,SF=1 溢出标志OF,运算结果有溢出,OF=1 OF(溢出)的判断: 二进制相加后,最高位与次高位异或。 例如 \[FFE8H +7FE6H=7FCEH \]\[1111 1111 1110 1000 +0111 1111 1110 0…...

2025年30个CRM系统盘点:哪款CRM系统适合你的企业? - SaaS软件

在数字化转型加速的2025年,客户关系管理(CRM)系统已成为企业提升竞争力的核心引擎。根据最新市场数据,全球CRM市场规模已突破1500亿美元,年复合增长率达15.3%,其中中国市场以28%的增速领跑全球。面对日益复杂的商业环境和客户需求,选择一款适合企业特性的CRM系统,已成为关…...

TSN Qav测试实践

1.前言我们在以往的文章中介绍了TSN相关的各个内容,包括《TSN(时间敏感网络)纯干货分享》、《TSN(Time-Sensitive Networking)时间敏感网络 协议导读:时间同步 | 延时 | 802.1Qav | 802.1Qch | 802.1Qbv | 802.1Qbu》、《基于TSN 802.1AS协议的时间同步分析(7种延时,1次…...

adobe illustrator中生成连续直角线段

001、工具栏选矩形工具 002、绘制一个矩形 003、鼠标切换到这里 004、 鼠标以横向拖动的方式选中一个边 005、键盘delete健删除 006、同样的方法删除下边这条边 。...

多重分形去趋势交叉相关性分析

多重分形去趋势交叉相关性分析(Multifractal Detrended Cross-Correlation Analysis, MF-DCCA) 1. 核心概念与理解 要理解MF-DCCA,我们最好将其拆解为几个部分:交叉相关性分析 (Cross-Correlation Analysis): 研究两个不同时间序列 \(x(i)\) 和 \(y(i)\) 之间在不同时间滞…...

智启燃气新未来丨众智鸿图精彩亮相2025燃气运营与安全研讨会 - 教程

智启燃气新未来丨众智鸿图精彩亮相2025燃气运营与安全研讨会 - 教程pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New…...

燕千云ITR平台引领服务流管理革命,构建企业客户服务智慧生态

燕千云ITR平台提出服务流作为企业第四大管理命脉,通过智能化解决方案重塑客户服务价值链。该平台整合多渠道受理、三线协同支持及AI知识沉淀三大核心功能,实现从被动响应到主动价值创造的转变。 当企业对资金流、物流、信息流的管理已成标配,决定未来竞争力的"第四大命…...

WPF 容器尺寸行为总结

WPF 容器尺寸行为总结 在 WPF 中,布局容器的尺寸来源可以分为三类:一类:尺寸主要取决于 父容器的约束 → “父大则大,父小则小” 一类:尺寸主要取决于 子元素的大小 → “子大则大,子小则小” 一类:尺寸基本固定,不跟随父或子变化📌 常见容器的尺寸行为对比容器 尺寸…...

在adobe illustrator中如何插入大于、小于号

001、1-4步骤 002、double click 。003、 效果 。...

三分钟了解流量卡的选择

选一张好用又省心的流量卡,信号是根本,但背后还有几个关键细节——做好功课再办卡,不花冤枉钱!1️⃣ 信号质量是核心基础中国移动用户数最多(截至2025年3月末:9.83亿户),电信4.2亿户,联通4.81亿户。用户多通常代表基站更多、覆盖更好,尤其是在偏远或室内场景优势更明…...

SARIMA算法

SARIMA模型 SARIMA模型,全称为季节性自回归积分滑动平均模型(Seasonal Autoregressive Integrated Moving Average Model),是时间序列分析中的一种重要模型,用于处理具有明显季节性特征的数据。它在ARIMA模型的基础上,增加了季节性因素的考量,使得模型能够更好地捕捉和预…...

【IEEE出版|EI检索稳定】第四届云计算、大数据应用与软件工程国际学术会议(CBASE 2025)

CBASE 2025旨在汇聚全球云计算、大数据、软件工程等计算机相关领域的顶尖学者与专业人士,打造一个高水平、国际化的学术交流平台,共同探讨最新研究进展与发展趋势。会议诚挚欢迎云计算、大数据、软件工程、网络安全、人工智能、计算机视觉、机器学习、智能计算等方向的专家学…...

Gitee推出革命性MCP Server:AI深度参与开发全流程 开启智能协作新时代

Gitee推出革命性MCP Server:AI深度参与开发全流程 开启智能协作新时代 在人工智能技术快速发展的当下,Gitee迈出了划时代的一步——正式发布官方MCP Server,将AI助手深度整合到软件开发全生命周期中。这一创新举措标志着代码托管平台从单纯的版本管理工具向智能开发平台的战…...

用机器语言实现循环

一般情况下实现循环 int result=0; for (int i=0;i<=100;i++){result +=1; }mov eax,0 #用eax保存result,初始值为0 mov edx,1 #用edx保存i,初始值为1 cmp edx,100 #比较i和100 if(i>100)如果大于一百就直接跳过 jg L2 #如果i>100跳转到L2 goto l2 L1: #循环主体…...

取证 - voasem

分类 内存取证 经常利用volatility分析取证文件后缀 .raw、.vmem、.img 常用命令(imageinfo,pslist,dumpfiles,memdump) 可疑的进程(notepad,cmd) 和磁盘取证结合起来考察 了解部分操作系统原理 常见文件后缀dmg,img命令 python3 vol.py -f [取证文件] 插件可以使用 -h…...

django对接drf-spectacular替代swagger

django对接drf-spectacular替代swagger 1.1、安装drf-spectacular pip install drf-spectacular pip install django-restframework1.2 配置 Django 设置 # settings.pyINSTALLED_APPS = [ # ... drf_spectacular, # 添加此项 rest_framework, # 确保 DRF 已添加 # ... ]REST_F…...

可画

https://www.canva.cn/...

Symbol VBRK: Invalid data type u SAP 事务成功新号码获取到 但是提交后提示失败如何处理

前几天用户提了个错误问题 Symbol "VBRK": Invalid data type "u" 提示说发票创建车工但是离开的时候报错 分析问题可能 增强失败 ST22检查没有讯息 今天经过更老的老师傅提示 SM14查看可能事务回滚了 赶紧查看了下 有错 点击 DEBUG发现是发票创建成功以…...

Oracle 19c asm单机OPatch补丁报错checkSystemCommandAvailable failed.

Oracle 19c asm单机OPatch补丁报错"checkSystemCommandAvailable" failed.一、OPatch Conflict Check As the Grid home user: % $ORACLE_HOME/OPatch/opatch prereq CheckConflictAgainstOHWithDetail -phBaseDir <UNZIPPED_PATCH_LOCATION>/36916690/3691259…...

three.js中怎么加载 .gltf/glb格式 文件

3D编辑器格式 用于特定应用程序(主要是3D编辑器):. .blend (Blender), .max (3d Studio Max), .mb and .ma (Maya), etc... 交换格式 有.OBJ, .DAE (Collada), .FBX.等格式。它们被设计出来用于3D编辑器之间交换信息的。因此,它们通常比所需的大得多(内含3D编辑器内所需要的…...

ollama如何安装使用

Ollama 是目前最流行的本地大语言模型(LLM)运行和管理的工具。它让下载、运行和体验各种开源模型(如 Llama、Mistral、Gemma 等)变得极其简单。 下面是从安装到使用的完整指南。一、安装 Ollama Ollama 支持 macOS、Linux 和 Windows(预览版)。 1. macOS方式一(推荐):…...