Java 10 新特性解析

文章目录

  • Java 10 新特性解析
    • 1. 引言
    • 2. 本地变量类型推断(JEP 286)
      • 2.1. 概述
      • 2.2. 使用场景
      • 2.3. 限制
      • 2.4. 与之前版本的对比
      • 2.5. 风格指南
      • 2.6. 示例代码
      • 2.7. 优点与注意事项
    • 3. 应用程序类数据共享(JEP 310)
      • 3.1. 概述
      • 3.2. 使用方法
      • 3.3. 示例代码
      • 3.4. 性能优势
      • 3.5. 与之前版本的对比
      • 3.6. 注意事项
    • 4. 额外的Unicode语言标签扩展(JEP 314)
      • 4.1. 概述
      • 4.2. 示例代码
      • 4.3. 与之前版本的对比
      • 4.4. 注意事项
    • 5. 根证书(JEP 319)
      • 5.1. 概述
      • 5.2. 影响
      • 5.3. 与之前版本的对比
    • 6. 基于时间的版本控制(JEP 322)
      • 6.1. 概述
      • 6.2. 示例
      • 6.3. 影响
    • 7. 其他增强功能
      • 7.1. JEP 304: 垃圾收集器接口
      • 7.2. JEP 307: G1的并行完全GC
      • 7.3. JEP 312: 线程本地握手
      • 7.4. JEP 313: 移除本地头生成工具(javah)
      • 7.5. JEP 316: 在替代内存设备上分配堆
      • 7.6. JEP 317: 实验性的基于Java的JIT编译器
    • 8. 其他API和选项
    • 9. 结论

Java 10(JDK 10)于2018年3月发布,标志着Java进入了一个新的快速迭代时代,采用了六个月的发布周期。作为这一新节奏的首个版本,Java 10引入了多项新特性和增强功能,旨在提升开发者的生产力、优化应用程序性能并增强安全性。本文将深入探讨Java 10的多个JDK增强提案(JEPs),重点介绍对开发者影响较大的特性,并提供完整的代码示例和使用指南,确保读者能够充分理解并在实际项目中应用这些改进。

在这里插入图片描述

1. 引言

Java 10是Java SE平台的一个重要里程碑,不仅因为它引入了新的语言特性和性能优化,还因为它标志着Java从传统的三年发布周期转向更快的六个月发布周期。这种变化使得新功能能够更快地交付给开发者,但也意味着非长期支持(LTS)版本(如Java 10)的支持时间仅为六个月,开发者可能更倾向于在生产环境中使用LTS版本(如Java 11)。尽管如此,Java 10的特性为开发者提供了宝贵的实验机会,并为后续版本奠定了基础。

本文将详细分析Java 10的多个JEP,重点关注对开发者日常工作有直接影响的特性,如本地变量类型推断(JEP 286)、应用程序类数据共享(JEP 310)、额外的Unicode语言标签扩展(JEP 314)、根证书(JEP 319)和基于时间的版本控制(JEP 322)。每个特性都将配有完整的代码示例,并在适用的情况下提供与之前版本的对比,以展示优化的效果。我们还将简要介绍其他内部改进,如垃圾收集器接口和线程本地握手等,以全面呈现Java 10的进步。

2. 本地变量类型推断(JEP 286)

2.1. 概述

本地变量类型推断是Java 10中最引人注目的特性,通过JEP 286引入。它允许开发者使用var关键字声明本地变量,而无需显式指定类型,编译器会根据初始化表达式的类型自动推断变量类型。这一特性旨在减少Java代码的冗余,提高可读性和开发效率,同时保持Java的静态类型安全。

在Java 10之前,声明本地变量需要显式指定类型,例如:

String message = "Hello, Java!";
List<String> list = new ArrayList<>();
Map<String, Integer> map = new HashMap<>();

这些声明在类型显而易见的情况下显得冗长,尤其是在处理复杂泛型类型时。Java 10的var关键字允许开发者简化代码:

var message = "Hello, Java!"; // 推断为 String
var list = new ArrayList<String>(); // 推断为 ArrayList<String>
var map = new HashMap<String, Integer>(); // 推断为 HashMap<String, Integer>

2.2. 使用场景

var关键字适用于以下场景:

  • 本地变量:必须有初始化器,编译器根据初始化器推断类型。
  • 增强型for循环:循环变量的类型可以推断。
  • 传统for循环:循环计数器的类型可以推断。
  • try-with-resources:资源变量的类型可以推断。

例如:

// 增强型 for 循环
var list = List.of("a", "b", "c");
for (var item : list) {System.out.println(item); // item 推断为 String
}// 传统 for 循环
for (var i = 0; i < 5; i++) {System.out.println(i); // i 推断为 int
}// try-with-resources
try (var reader = new BufferedReader(new FileReader("file.txt"))) {String line = reader.readLine();System.out.println(line);
}

2.3. 限制

var的使用有以下限制:

  • 仅限于本地变量,不能用于方法参数、构造函数参数、方法返回值、字段或catch块参数。
  • 必须有初始化器,否则编译器无法推断类型。例如,var x;会导致编译错误。
  • 不支持数组初始化器,如var arr = {1, 2, 3};是无效的。
  • 不支持lambda表达式参数(此功能在Java 11中引入)。

例如,以下代码是无效的:

var x; // 错误:无法推断类型
var arr = {1, 2, 3}; // 错误:不支持数组初始化器
public void method(var param) {} // 错误:不能用于方法参数

2.4. 与之前版本的对比

在Java 7中,引入了菱形操作符(<>),允许在泛型实例化时省略类型参数,例如:

List<String> list = new ArrayList<>();

然而,左侧仍需显式声明类型。Java 10的var进一步减少了这种冗余,使代码更简洁。需要注意的是,var推断的是初始化器的具体类型,而不是接口类型。例如:

var list = new ArrayList<String>(); // 推断为 ArrayList<String>,而不是 List<String>

如果需要接口类型,仍需显式声明:

List<String> list = new ArrayList<>();

2.5. 风格指南

为了确保var的使用不影响代码可读性,OpenJDK提供了风格指南,以下是关键建议:

  • G1:选择有意义的变量名:变量名应反映其用途,例如var customers = dbconn.executeQuery(query);优于var custList = dbconn.executeQuery(query);
  • G2:最小化变量作用域:较小的作用域降低类型变化导致错误的风险。
  • G3:当初始化器提供足够类型信息时使用var:例如,var outputStream = new ByteArrayOutputStream();
  • G4:分解复杂表达式:使用var将长方法链拆分为更易读的本地变量。
  • G5:不必过分强调“面向接口编程”:对于本地变量,推断具体类型(如ArrayList)的影响较小。
  • G6:注意var与菱形操作符的结合:避免var list = new ArrayList<>();,因为它推断为ArrayList<Object>
  • G7:谨慎使用数字字面量var x = 100;推断为int,若需要long,需写var x = 100L;

2.6. 示例代码

以下是一个综合示例,展示var在不同场景中的使用:

import java.util.*;
import java.io.*;public class VarExample {public static void main(String[] args) throws IOException {// 基本类型var message = "Hello, Java 10!";System.out.println(message); // 输出:Hello, Java 10!// 集合var numbers = new ArrayList<Integer>();numbers.add(1);System.out.println(numbers); // 输出:[1]// 流操作var stream = numbers.stream();var sum = stream.mapToInt(Integer::intValue).sum();System.out.println(sum); // 输出:1// try-with-resourcestry (var reader = new BufferedReader(new FileReader("example.txt"))) {var line = reader.readLine();System.out.println(line);}// 匿名类var runnable = new Runnable() {public void run() {System.out.println("Running!");}};runnable.run();}
}

2.7. 优点与注意事项

优点

  • 减少样板代码,提高可读性。
  • 与其他语言(如C#、Scala)的类型推断功能对齐。
  • 无运行时开销,类型在编译时确定。

注意事项

  • 过度使用可能降低代码可读性,尤其当初始化器类型不明显时。
  • 不支持动态类型,Java仍为静态类型语言。
  • 需遵循风格指南,避免常见陷阱,如与菱形操作符结合导致推断为Object

有关更多详细信息,请参阅JEP 286: Local-Variable Type Inference。

3. 应用程序类数据共享(JEP 310)

3.1. 概述

类数据共享(CDS)是Java 5引入的一项功能,允许多个JVM实例共享系统类的元数据,以减少内存占用和加快启动时间。Java 10通过JEP 310扩展了CDS,允许将应用程序类包含在共享存档中,进一步优化性能,特别是在运行多个JVM实例的场景中,如微服务或容器化环境。

3.2. 使用方法

要使用应用程序CDS,需执行以下步骤:

  1. 生成共享存档:运行应用程序时,使用-XX:ArchiveClassesAtExit选项记录加载的类。
  2. 使用共享存档:启动应用程序时,使用-XX:SharedArchiveFile选项加载存档。

示例命令:

# 生成存档
java -XX:ArchiveClassesAtExit=app.jsa -cp app.jar com.example.App# 使用存档
java -XX:SharedArchiveFile=app.jsa -cp app.jar com.example.App

3.3. 示例代码

以下是一个简单的应用程序示例:

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

运行以下命令生成存档:

java -XX:ArchiveClassesAtExit=app.jsa -cp app.jar App

然后使用存档启动应用程序:

java -XX:SharedArchiveFile=app.jsa -cp app.jar App

3.4. 性能优势

根据JEP 310的成功指标:

  • 在Java EE应用服务器上,6个JVM实例可节省约340MB内存。
  • JEdit基准测试的启动时间可提高20-30%。
  • 嵌入式Felix基准测试显示4个JVM进程的内存使用量减少18%。

这些优势取决于加载的类和堆使用情况,但在多实例场景中尤为显著。

3.5. 与之前版本的对比

在Java 9及之前,CDS仅限于系统类(由引导类加载器加载)。Java 10扩展了CDS,支持应用程序类路径中的类以及由内置平台和系统类加载器加载的类。未来的版本(如JEP 350)进一步支持动态CDS存档。

3.6. 注意事项

  • 共享存档的存储格式未标准化,可能因JVM版本而异。
  • Java 10不支持用户定义模块(--module-path)的类存档,需等待后续版本。

有关更多详细信息,请参阅JEP 310: Application Class-Data Sharing。

4. 额外的Unicode语言标签扩展(JEP 314)

4.1. 概述

Java 10通过JEP 314增强了java.util.Locale类,支持BCP 47语言标签的额外Unicode扩展。这些扩展允许更精确地控制区域设置相关的行为,如货币、每周第一天、区域覆盖和时区。Java 7已支持ca(日历)和nu(数字)扩展,Java 10新增了以下扩展:

  • cu:货币类型
  • fw:每周第一天
  • rg:区域覆盖
  • tz:时区

4.2. 示例代码

以下示例展示如何使用这些扩展:

import java.util.*;
import java.text.*;public class LocaleExample {public static void main(String[] args) {// 指定欧元货币Locale localeEUR = Locale.forLanguageTag("en-US-u-cu-eur");NumberFormat currencyFormat = NumberFormat.getCurrencyInstance(localeEUR);System.out.println(currencyFormat.format(1234.56)); // 输出:€1,234.56// 指定每周第一天为星期一Locale localeFW = Locale.forLanguageTag("en-US-u-fw-mon");Calendar cal = Calendar.getInstance(localeFW);System.out.println(cal.getFirstDayOfWeek() == Calendar.MONDAY); // 输出:true}
}

4.3. 与之前版本的对比

Java 9支持的canu扩展已为日历和数字格式提供了基础支持。Java 10通过新增cufwrgtz扩展,进一步增强了国际化的灵活性。例如,开发者现在可以轻松指定非默认货币或时区,而无需复杂的配置。

4.4. 注意事项

  • 扩展键对大小写不敏感,但Locale类会将键和值规范化为小写。
  • 扩展值必须符合BCP 47的语法要求,否则可能抛出异常。
  • 开发者需验证扩展是否被目标API(如NumberFormatCalendar)支持。

有关更多详细信息,请参阅JEP 314: Additional Unicode Language-Tag Extensions。

5. 根证书(JEP 319)

5.1. 概述

Java 10通过JEP 319在JDK的cacerts密钥库中引入了一组默认的根认证机构(CA)证书。在OpenJDK 9中,cacerts密钥库为空,导致无法在不提供自定义信任存储的情况下建立TLS连接。Java 10通过包含Oracle Java SE根CA计划的证书解决了这一问题。

5.2. 影响

此特性简化了安全连接的配置,确保应用程序可以直接与使用受信任CA颁发的证书的服务器建立HTTPS连接。例如:

import javax.net.ssl.*;
import java.net.URL;public class TLSTest {public static void main(String[] args) throws Exception {URL url = new URL("https://www.oracle.com");HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();conn.connect();System.out.println("Connected successfully!");}
}

在Java 10中,上述代码无需额外配置即可运行,因为cacerts包含了必要的根证书。

5.3. 与之前版本的对比

在OpenJDK 9中,开发者需要手动配置信任存储,否则TLS连接会失败。Java 10的默认根证书消除了这一障碍,提高了开发效率和安全性。

有关更多详细信息,请参阅JEP 319: Root Certificates。

6. 基于时间的版本控制(JEP 322)

6.1. 概述

Java 10通过JEP 322引入了基于时间的版本控制方案,以适应新的六个月发布周期。版本字符串采用$FEATURE.$INTERIM.$UPDATE.$PATCH格式:

  • $FEATURE:每六个月递增的功能发布号,如10、11。
  • $INTERIM:保留为0,用于未来的中间更新。
  • $UPDATE:安全更新或补丁的编号。
  • $PATCH:紧急修复的编号。

例如,Java 10的初始版本为10.0.0,更新版本为10.0.1、10.0.2等。下一个功能发布为Java 11(11.0.0)。

6.2. 示例

检查Java版本:

public class VersionCheck {public static void main(String[] args) {System.out.println(System.getProperty("java.version")); // 输出:10.0.0}
}

6.3. 影响

此版本控制方案使开发者更容易跟踪发布周期和支持状态。Java 10作为非LTS版本,建议用于开发和测试,而生产环境可能更适合LTS版本(如Java 11)。

有关更多详细信息,请参阅JEP 322: Time-Based Release Versioning。

7. 其他增强功能

Java 10还包括以下内部改进,对开发者影响较小,但对JVM维护和性能优化至关重要:

7.1. JEP 304: 垃圾收集器接口

改进了垃圾收集器(GC)的源代码隔离,使添加或移除GC实现更加容易。这主要惠及JVM开发者,但为未来的GC创新奠定了基础。

7.2. JEP 307: G1的并行完全GC

G1垃圾收集器是Java 9的默认GC,但其完全GC(Full GC)为单线程,可能导致性能瓶颈。Java 10通过JEP 307并行化完全GC,使用与年轻代和混合收集相同的并行工作线程。例如,可通过-XX:ParallelGCThreads选项控制线程数:

java -XX:ParallelGCThreads=4 -jar app.jar

与之前版本的对比:在Java 9中,G1的完全GC为单线程,可能导致较长的暂停时间。并行完全GC显著提高了性能,尤其是在大堆场景中。

7.3. JEP 312: 线程本地握手

此特性允许在不执行全局VM安全点的情况下对单个线程执行回调,减少延迟。安全点是JVM暂停所有线程以执行GC等操作的点,全局安全点可能导致显著的延迟。线程本地握手提高了JVM的响应性,尤其在多线程应用中。

7.4. JEP 313: 移除本地头生成工具(javah)

自Java 8起,javac支持-h选项生成本地头文件,javah工具变得多余。Java 10通过JEP 313移除javah,开发者应使用以下命令:

javac -h . NativeExample.java

示例代码:

public class NativeExample {public native void nativeMethod();
}

运行javac -h . NativeExample.java将生成NativeExample.h文件。

7.5. JEP 316: 在替代内存设备上分配堆

允许HotSpot VM在替代内存设备(如NV-DIMM)上分配Java堆,适用于特殊硬件环境,对普通开发者影响较小。

7.6. JEP 317: 实验性的基于Java的JIT编译器

引入Graal编译器作为Linux/x64平台的实验性JIT编译器,可通过以下选项启用:

java -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI -XX:+UseJVMCICompiler -jar app.jar

Graal为未来的JVM性能优化(如Project Metropolis)奠定了基础,但不建议在生产环境中使用。

有关更多详细信息,请参阅:

  • JEP 304: Garbage Collector Interface
  • JEP 307: Parallel Full GC for G1
  • JEP 312: Thread-Local Handshakes
  • JEP 313: Remove the Native-Header Generation Tool
  • JEP 316: Heap Allocation on Alternative Memory Devices
  • JEP 317: Experimental Java-Based JIT Compiler

8. 其他API和选项

Java 10还引入了一些新的API和选项,增强了开发者的工具集。以下是一些关键更新:

类别特性/增强功能详细信息
core-libs/java.utilOptional.orElseThrow() 方法新增方法,作为get方法的首选替代,明确抛出异常。
core-libs/java.util:collections创建不可修改集合的API新增List.copyOfSet.copyOfMap.copyOfCollectors.toUnmodifiableList等方法。
core-svc/java.lang.management禁用JRE最后使用跟踪的系统属性新增jdk.disableLastUsageTracking属性,可通过-Djdk.disableLastUsageTracking=true设置。
security-libs/javax.net.sslTLS会话哈希和扩展主密钥支持支持RFC 7627,可通过jdk.tls.useExtendedMasterSecret=false禁用。

这些API提供了更便捷的操作方式,例如:

import java.util.*;public class CollectionExample {public static void main(String[] args) {var list = List.of("a", "b", "c");var unmodifiableList = List.copyOf(list); // 创建不可修改副本System.out.println(unmodifiableList); // 输出:[a, b, c]}
}

9. 结论

Java 10通过其多个JEP为开发者带来了显著的改进,从本地变量类型推断的便利性到应用程序类数据共享的性能优化,再到根证书和Unicode扩展的安全性与国际化增强。这些特性不仅提高了开发效率,还为Java的未来发展奠定了基础。尽管Java 10作为非LTS版本的支持时间较短,但其特性为开发者提供了宝贵的实验机会,并为Java 11等LTS版本铺平了道路。

通过本文的代码示例和详细解释,您应该能够自信地在项目中应用这些新特性。建议开发者参考官方文档和JEP页面以获取更深入的技术细节,并根据项目需求选择是否升级到Java 10或等待LTS版本。

引用:

  • JEP 286: Local-Variable Type Inference
  • JEP 310: Application Class-Data Sharing
  • JEP 314: Additional Unicode Language-Tag Extensions
  • JEP 319: Root Certificates
  • JEP 322: Time-Based Release Versioning
  • JDK 10 Release Notes
  • Local Variable Type Inference Style Guidelines

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

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

相关文章

【WRF工具】服务器中安装编译GrADS

目录 安装编译 GrADS 所需的依赖库 conda下载库包 安装编译 GrADS 编译前检查依赖可用性 安装编译 GrADS 参考 安装编译 GrADS 所需的依赖库 以统一方式在 $HOME/WRFDA_LIBS/grads_deps 下安装所有依赖: # 选择一个目录用于安装所有依赖库 export DIR=$HOME/WRFDA_LIBS库包1…

数据结构之队列(C语言)

1.队列的定义&#xff1a; 队列&#xff08;Queue&#xff09;是一种基础且重要的线性数据结构&#xff0c;遵循先进先出&#xff08;FIFO&#xff09;​​ 原则&#xff0c;即最早入队的元素最先出队&#xff0c;与栈不同的是出队列的顺序是固定的。队列具有以下特点&#xff…

C#开发基础之深入理解“集合遍历时不可修改”的异常背后的设计

前言 欢迎关注【dotnet研习社】&#xff0c;今天我们聊聊一个基础问题“集合已修改&#xff1a;可能无法执行枚举操作”背后的设计。 在日常 C# 开发中&#xff0c;我们常常会操作集合&#xff08;如 List<T>、Dictionary<K,V> 等&#xff09;。一个新手开发者极…

【工具】图床完全指南:从选择到搭建的全方位解决方案

前言 在数字化内容创作的时代&#xff0c;图片已经成为博客、文档、社交媒体等平台不可或缺的元素。然而&#xff0c;如何高效、稳定地存储和分发图片资源&#xff0c;一直是内容创作者面临的重要问题。图床&#xff08;Image Hosting&#xff09;作为专门的图片存储和分发服务…

深度学习篇---PaddleDetection模型选择

PaddleDetection 是百度飞桨推出的目标检测开发套件&#xff0c;提供了丰富的模型库和工具链&#xff0c;覆盖从轻量级移动端到高性能服务器的全场景需求。以下是核心模型分类、适用场景及大小选择建议&#xff08;通俗易懂版&#xff09;&#xff1a;一、主流模型分类及适用场…

cmseasy靶机密码爆破通关教程

靶场安装1.首先我们需要下载一个cms靶场CmsEasy_7.6.3.2_UTF-8_20200422,下载后解压在phpstudy_pro的网站根目录下。2.然后我们去访问一下安装好的网站&#xff0c;然后注册和链接数据库3.不知道自己数据库密码的可以去小皮面板里面查看4.安装好后就可以了来到后台就可以了。练…

【C语言】指针深度剖析(一)

文章目录一、内存和地址1.1 内存的基本概念1.2 编址的原理二、指针变量和地址2.1 取地址操作符&#xff08;&&#xff09;2.2 指针变量和解引用操作符&#xff08;*&#xff09;2.2.1 指针变量2.2.2 指针类型的解读2.2.3 解引用操作符2.3 指针变量的大小三、指针变量类型的…

半导体企业选用的跨网文件交换系统到底应该具备什么功能?

在半导体行业的数字化转型过程中&#xff0c;跨网文件交换已成为连接研发、生产、供应链的关键纽带。半导体企业的跨网文件交换不仅涉及设计图纸、工艺参数等核心知识产权&#xff0c;还需要满足跨国协同、合规审计等复杂需求。那么&#xff0c;一款适合半导体行业的跨网文件交…

影刀RPA_初级课程_玩转影刀自动化_网页操作自动化

声明&#xff1a;相关内容来自影刀学院&#xff0c;本文章为自用笔记&#xff0c;切勿商用&#xff01;&#xff08;若有侵权&#xff0c;请联络删除&#xff09; 1. 基本概念与操作 1.1 正确处理下拉框元素&#xff08;先判断页面元素&#xff0c;后进行流程编制&#xff09;…

Spark初探:揭秘速度优势与生态融合实践

更多推荐阅读 Spark与Flink深度对比&#xff1a;大数据流批一体框架的技术选型指南-CSDN博客 LightProxy使用操作手册-CSDN博客 Sentry一看就会教程_sentry教程-CSDN博客 微前端架构解析&#xff1a;核心概念与主流方案特性对比_微前端方案对比-CSDN博客 目录 Spark为何比Hadoo…

详谈OSI七层模型和TCP/IP四层模型以及tcp与udp为什么是4层,http与https为什么是7层

一、网络模型&#xff1a;OSI七层 vs TCP/IP四层OSI七层模型 (理论参考模型):目的&#xff1a;提供一个标准化的理论框架&#xff0c;用于理解网络通信过程和各层的功能划分&#xff0c;促进不同厂商设备的互操作性。它是一个理想化的模型。分层 (从下到上):物理层&#xff1a;…

ClickHouse 高性能实时分析数据库-索引与数据跳过(查询的“瞬移”能力)

告别等待&#xff0c;秒级响应&#xff01;这不只是教程&#xff0c;这是你驾驭PB级数据的超能力&#xff01;我的ClickHouse视频课&#xff0c;凝练十年实战精华&#xff0c;从入门到精通&#xff0c;从单机到集群。点开它&#xff0c;让数据处理速度快到飞起&#xff0c;让你…

Jetpack - Room(Room 引入、Room 优化)

一、Room 引入 1、基本介绍 Room 在 SQLite 上提供了一个抽象层&#xff0c;以便在充分利用 SQLite 的强大功能的同时&#xff0c;能够流畅地访问数据库&#xff0c;官方强烈建议使用 Room 而不是 SQLite 2、演示 &#xff08;1&#xff09;Setting 模块级 build.gradle depend…

【江科大CAN】2.1 STM32 CAN外设(上)

2.1 STM32 CAN外设&#xff08;上&#xff09;2.1.1 STM32 CAN外设简介2.1.2 外围电路设计2.1.3 STM32 CAN内部结构2.1.4 发送流程详解2.1.5 接收流程详解2.1.6 关键配置位总结STM32 CAN外设讲解 大家好&#xff0c;欢迎继续观看CAN总线入门教程。本节开始&#xff0c;我们正式…

人工智能技术革命:AI工具与大模型如何重塑开发者工作模式与行业格局

引言&#xff1a;AI技术爆发的时代背景过去五年间&#xff0c;人工智能领域经历了前所未有的爆发式增长。从2020年GPT-3的横空出世到2023年多模态大模型的全面突破&#xff0c;AI技术已经从实验室走向了产业应用的前沿。开发者作为技术生态的核心推动者&#xff0c;其工作模式正…

傅里叶变换

傅里叶变换:运用频域的出发点就是能够将波形从时域变换到频域&#xff0c;用傅里叶变换可以做到这一点。有如下3种傅里叶变换类型&#xff1a;1.傅里叶积分(FI); 2.离散傅里叶变换(DFT); 3.快速傅里叶变换(FFT)。傅里叶积分是一种将时域的理想数学表达变换成频域描述的数学技术…

【IQA技术专题】纹理相似度图像评价指标DISTS

纹理一致性图像评价指标: Image Quality Assessment: Unifying Structure and Texture Similarity&#xff08;2020 PAMI&#xff09;专题介绍一、研究背景二、方法总览2.1 初始变换2.2 纹理表示和结构表示2.3 DISTS指标2.4 优化DISTS指标三、实验结果四、总结本文将对统一图像…

windows下Docker安装路径、存储路径修改

一、命令行指定安装路径​ ​​下载安装包​​&#xff1a;从Docker官网获取安装程序&#xff08;如Docker Desktop Installer.exe&#xff09;。​​运行PowerShell​​&#xff1a; & "H:\Docker Desktop Installer.exe" install --installation-dir"F:…

thingsboard 自定义动作JS编程

在 ThingsBoard 中实现 自定义动作&#xff08;Custom Action&#xff09;的 JavaScript 编程&#xff0c;主要通过“Custom action (with HTML template&#xff09;”方式完成&#xff0c;适用于创建弹窗、编辑实体、控制设备等交互行为。 实现步骤&#xff08;以添加设备或资…

Spring Boot 简单接口角色授权检查实现

一、背景与目标在Spring Boot应用开发中&#xff0c;接口级别的权限控制是系统安全的重要组成部分。本文将介绍一种简单直接的接口角色授权检查实现方案&#xff0c;适合快速开发和安全合规检查场景。二、技术方案概述本方案采用自定义注解拦截器的方式实现&#xff0c;具有以下…