Java 22 正式发布,一文了解全部新特性
就在昨晚,Java 22正式发布!该版本提供了 12 项功能增强,其中包括 7 项预览功能和 1 项孵化器功能。它们涵盖了对 Java 语言、API、性能以及 JDK 中包含的工具的改进。
下面就来一起学习一下该版本都更新了哪些新特性!
JEP 456 – 未命名变量和模式:当需要但未使用变量声明或嵌套模式时,提高了可读性。两者都由下划线字符表示。
价值
- 捕获开发人员的意图,即未使用给定的绑定或 lambda 参数,并强制执行该属性以澄清程序并减少出错的机会。
- 通过识别必须声明(例如,在 catch 子句中)但未使用的变量,提高所有代码的可维护性。
- 允许多个模式出现在单个 case 标签中,如果它们都没有声明任何模式变量。
- 通过消除不必要的嵌套类型模式来提高记录模式的可读性。
在构造函数中,允许不引用正在创建的实例的语句出现在显式构造函数调用之前。
价值
- 为开发人员提供了更大的自由来表达构造函数的行为,从而可以更自然地放置目前必须纳入辅助静态方法、辅助中间构造函数或构造函数参数中的逻辑。
- 保留构造函数在类实例化期间按自上而下顺序运行的现有保证,确保子类构造函数中的代码不会干扰超类实例化。
- 不需要对 Java 虚拟机进行任何更改。此 Java 语言功能仅依赖于 JVM 验证和执行构造函数中显式构造函数调用之前出现的代码的当前能力。
字符串模版的第2个预览版,关于该功能之前DD给大家介绍过,更多细节可以看看之前的这篇文章:String Templates(字符串模版)
价值
- 通过轻松表达包含运行时计算值的字符串,简化了 Java 程序的编写。
- 增强混合文本和表达式的表达式的可读性,无论文本适合单个源行(如字符串文字)还是跨越多个源行(如文本块)。
- 通过支持模板及其嵌入表达式的值的验证和转换,提高 Java 程序的安全性,这些程序从用户提供的值组成字符串并将其传递到其他系统(例如,构建数据库查询)。
- 通过允许 Java 库定义字符串模板中使用的格式化语法来保留灵活性。
- 简化了接受非 Java 语言(例如 SQL、XML 和 JSON)编写的字符串的 API 的使用。
- 允许创建根据文字文本和嵌入表达式计算的非字符串值,而无需通过中间字符串表示形式进行传输。
隐式声明的类和实例主要方法(2nd 预览)- JEP 463
学生可以编写他们的第一个 Java 程序,而无需了解为大型程序设计的语言功能。学生无需使用单独的语言方言,而是可以为单类程序编写简化的声明,然后随着技能的增长无缝扩展他们的程序以使用更高级的功能。关于该特性,之前DD也介绍过,更多细节可见这篇文章:未命名类和实例的Main方法
价值
- 加速 Java 学习
- 为 Java 编程提供了一个平滑的入门通道,以便教师可以循序渐进地介绍概念。
- 帮助学生以简洁的方式编写基本程序,并随着他们的技能增长而优雅地扩展他们的代码。
- 减少编写简单程序(例如:脚本和命令行实用程序)的方式。
- 不引入单独的初学者工具链;学生程序应该使用与编译和运行任何 Java 程序相同的工具来编译和运行。
外部函数和内存 API – JEP 454
允许 Java 程序与 Java 运行时之外的代码和数据进行互操作。通过有效地调用外部函数(即 JVM 外部的代码),并安全地访问外部内存(即不受 JVM 管理的内存),API 使 Java 程序能够调用本机库并处理本机数据,而不会出现脆弱性和危险。JNI。
价值
- 生产力:用简洁、可读且纯 Java API 取代脆弱的本机方法和 Java 本机接口 (JNI)。
- 性能:提供对外部函数和内存的访问,其开销与 JNI 和 sun.misc.Unsafe 相当(如果不是更好的话)。
- 广泛的平台支持:允许在 JVM 运行的每个平台上发现和调用本机库。
- 一致性:提供在多种内存(例如本机内存、持久内存和托管堆内存)中操作无限大小的结构化和非结构化数据的方法。
- 健全性:保证没有释放后使用错误,即使在多个线程之间分配和释放内存时也是如此。
- 完整性:允许程序使用本机代码和数据执行不安全的操作,但默认警告用户此类操作。
类文件 API(预览版)- JEP 457,提供用于解析、生成和转换 Java 类文件的标准 API。
价值
- 该API允许依赖它的框架和程序自动支持最新JDK中的最新类文件,以便可以快速、轻松地采用以类文件表示的新语言和VM功能。
Stream Gatherers(预览版)- JEP 461,增强了 Stream API 以支持自定义中间操作。这将允许流管道以现有内置中间操作不易实现的方式转换数据。
价值
- 通过使流中的常见自定义操作更加灵活和富有表现力,提高开发人员的工作效率和代码可读性。尽可能允许中间操作操作无限大小的流。
结构化并发(2nd 预览版)- JEP 462,简化并发编程。结构化并发将在不同线程中运行的相关任务组视为单个工作单元,从而简化错误处理和取消、提高可靠性并增强可观察性。
价值
- 通过推广一种编程风格来简化并发代码的开发,这种编程风格可以消除因取消和关闭而产生的常见风险(例如线程泄漏和取消延迟),并提高并发代码的可观察性。
范围值(2nd 预览)- JEP 464,实现线程内和线程间不可变数据的高效共享。
价值
- 易于使用 – 提供一个编程模型来在线程内以及与子线程共享数据,以简化有关数据流的推理。
- 可理解性——使共享数据的生命周期从代码的语法结构中可见。
- 鲁棒性——确保调用者共享的数据只能由合法的被调用者检索。
- 性能——将共享数据视为不可变,以允许大量线程共享,并实现运行时优化。
矢量 API(7th 孵化器)- JEP 460,一个用于表达向量计算的 API,可在运行时可靠地在支持的 CPU 架构上编译为最佳向量指令,从而实现优于等效标量计算的性能。此 JEP 建议在 JDK 22 中重新孵化该 API,相对于JDK 21。该实现包括错误修复和性能增强。我们包括以下显着变化:
- 支持使用任何原始元素类型的数组支持的堆 MemorySegments 进行向量访问。以前的访问仅限于由字节数组支持的堆 MemorySegment。
价值
- 提供清晰简洁的 API,能够清晰简洁地表达各种向量计算,这些向量计算由循环内组成的向量运算序列组成,并且可能还包含控制流。
- 该 API 设计为与 CPU 架构无关,可在支持向量指令的多种架构上实现。
- 在 x64 和 AArch64 架构上提供可靠的运行时编译和性能。
G1 的区域固定 – JEP 423,通过在 G1 中实现区域固定来减少延迟,以便在 Java 本机接口 (JNI) 关键区域期间无需禁用垃圾收集。
价值
- 使用 JNI 时,Java 线程无需在 G1 GC 操作完成之前等待,从而提高开发人员的工作效率。
启动多文件源代码程序 – JEP 458,允许用户运行作为多个 Java 源代码文件提供的程序,而无需先进行编译。
价值
- 通过使从小程序到大型程序的过渡更加渐进,提高开发人员的工作效率,使开发人员能够选择是否以及何时配置构建工具。
- 请注意,预览功能已完全指定并完全实现了 Java SE 平台的语言或 VM 功能,但它们是暂时的。它们在 JDK 功能版本中提供,以便开发人员根据实际使用情况提供反馈,然后再在未来版本中永久保留。这也为工具供应商提供了在最终确定为 Java SE 标准之前致力于支持功能的机会。
- 孵化器模块中的 API 将非最终 API 和非最终工具交给开发人员和用户,以收集反馈,最终提高 Java 平台的质量。
- 除了 JEP 中描述的更改之外,发行说明中还列出了许多较小的更新,许多应用程序开发人员和系统管理员都会对此感兴趣。其中包括弃用过时的 API 和删除以前弃用的 API。
Java 22 发行说明中还有一些其他关键更新:
- 向 keytool 和 jarsigner 添加附加算法。
- 垃圾收集器吞吐量的提高,尤其是与“年轻”垃圾相关的情况。
- 更好的系统模块描述符版本报告。
- 改进了本机代码的“wait”处理选项。
- Unicode 通用区域设置数据存储库已更新至版本 44。
- 类型注释支持从字节码加载的类型。
- ForkJoinPool 和 ForJoinTasks 现在可以更好地处理不间断任务。
- 配置客户端与服务器 TLS 连接属性的额外灵活性。
- 改进了本机内存跟踪,包括报告峰值使用情况的能力
最后注意:JDK 22 是通过六个月的发布节奏按时交付的 13th 功能版本。由于预期改进源源不断,这种程度的可预测性使开发人员能够轻松管理创新的采用。Oracle 不会为 JDK 22 提供长期支持,在 2023 年 9 月之前提供更新,之后它将被 Oracle JDK 23 取代。最近的长期维护版本是Java 21,更多关于Java新特性的解读和学习欢迎关注《Java 新特性解读》: https://www.didispace.com/java-features/
C 语言源程序文件扩展名及相关知识详解
本文就来聊一聊C语言源程序文件拼接后生成的文件扩展名是什么?,以及C++源程序文件扩展名对应的知识点是什么。希望对大家有所帮助,别忘了收藏本站哦。
在Linux平台上,C语言源代码文件一般以.c为扩展名,预处理后的文件扩展名一般为.i,编译器生成的程序的汇编代码一般以.s为扩展名,生成的可执行文件一般以.out为扩展名。
编辑文件时,源代码的扩展名为.CPP,C++头文件的扩展名为.H。编译源程序文件会将其转换为扩展名为.obj的目标文件。链接将一个或多个目标文件与程序用到的库文件链接起来,形成可在操作系统上直接运行的可执行程序.exe。
链接后的可执行文件的后缀名为.exe,源文件的后缀只是为了表明该文件包含某种语言的代码(例如.c文件包含C语言代码),这样方便程序员和编译器更容易区分,并且不会导致文件内部格式的改变。
C语言源文件的后缀为“.c”,编译后的文件后缀为“.obj”,链接后的可执行文件的后缀为“.exe”。C语言是一种面向过程、抽象的通用编程语言,广泛应用于底层开发。C语言高效、灵活、功能丰富、表现力强。
源文件通常为.c或.cpp,头文件为.h,编译文件为.obj,链接文件为.exe。
如果只生成一个文件,那么本题答案为B。编译()后生成目标文件,后缀为:.obj。也就是机器码。然后链接器()连接生成可执行文件,后缀为:.exe。最后运行命令(go)就可以直接运行这个.exe文件了。
C语言源程序文件连接后生成的文件的扩展名是什么?
C语言源程序文件的扩展名是cpp。C++是C语言的继承者,既可以进行C语言的过程式编程,又可以进行基于抽象数据类型的面向对象编程,面向对象编程的特点是继承性和多态性,C++擅长面向对象编程。
C语言源程序的文件扩展名是.c。 源程序:程序可以用高级语言或汇编语言编写。用高级语言或汇编语言编写的程序称为源程序。C语言源程序的文件扩展名是“.c”。源程序不能直接在计算机上执行。需要使用“编译器”将其编译成二进制程序。
C语言源程序的扩展名是“.c”,由C语言组成的指令序列称为C源程序,源程序文件的后缀为“.c”。注意:在大多数操作系统中,C源代码文件后缀的大小写并不重要,例如“index.C”和“index.c”指的是同一个文件;但是
C语言源程序的后缀为.c,编译后的程序后缀为.obj或.o,链接后生成的可执行文件的后缀为.exe。C语言是一种面向过程的、抽象的、通用的编程语言。广泛应用于底层开发。C语言可以以简单的方式编译和处理底层内存。
C语言源程序文件的扩展名是什么?
面向过程的C语言演化为面向对象的C++语言,同时C++语言又完美兼容C语言,CPP的由来是C++的英文拼写是C Plus Plus,其中Plus是plus的英文拼写,取第一个字母后不要把C++简写为cpp,.cpp是C++语言的标准源文件扩展名。
.cpp~~~一般默认是.cpp因为也可以写C代码,但是.c不能写C++代码
C++语言的编译单元是程序文件,扩展名为.cpp。补充:C语言是C++的基础,C++和C语言在很多方面是兼容的。C语言是一种结构化语言,其重点是算法和数据。C程序的设计主要关注如何处理输入(或循环)
C++ 源代码文件的常见扩展名是 .cpp。在 C++ 编程中,源代码通常保存在扩展名为 .cpp 的文本文件中。这些文件包含 C++ 编程语言的源代码,可以使用文本编辑器或除 .cpp 扩展名外,还有其他与 C++ 源代码相关的扩展名。
C++源程序文件的扩展名是.cpp。C++是C语言的继承者,既可以进行C语言中的过程式编程,又可以进行具有抽象数据类型特征的面向对象编程。面向对象编程的特点是继承性和多态性。C++擅长面向对象编程。
c++的扩展是什么
在操作系统下,C语言源程序的后缀为.c。
1. C语言源程序可以由一个或多个源文件组成。 2. 每个源文件可以由一个或多个函数组成。 3. 一个源程序不管由多少个文件组成,都只有一个主函数,即main函数。 4. 源程序中可以有预处理命令(命令只能
C语言源程序的后缀为.c,编译后的程序后缀为.obj或.o,链接后生成的可执行文件的后缀为.exe。C语言是一种面向过程的、抽象的、通用的编程语言。广泛应用于底层开发。C语言可以以简单的方式编译和处理底层内存。
C语言源程序文件的后缀为.c,C语言头文件的后缀为.h,C++源文件的后缀为“cpp”。C语言是一种面向过程的计算机编程语言,与C++、Java等面向过程的对象编程语言不同。C语言的设计目标是提供一种编译和处理
C语言源程序文件的后缀为“C”,对于计算机语言来说,源代码文件都会有特定的后缀,比如C++源代码文件的后缀为“.cpp”,C源代码文件的后缀为“.py”。有一点需要强调
C语言源程序文件的扩展名是.c,C语言程序源代码文件都以.c作为文件后缀,这是常见的C语言源文件扩展名,c文件是源文件,只有经过编译、链接后才能被编译成C语言源程序,成为中间目标文件。
在Linux平台上,C语言源代码文件一般以.c为扩展名,预处理后的文件扩展名一般为.i,编译器生成的程序的汇编代码一般以.s为扩展名,生成的可执行文件一般以.out为扩展名。
C语言源程序文件的后缀是什么?
C语言源程序文件的后缀为.c,C语言头文件的后缀为.h,C++源文件的后缀为“cpp”。C语言是一种面向过程的计算机编程语言,与C++、Java等面向过程的对象编程语言不同。C语言的设计目标是提供一种编译和处理
C源程序的扩展名是C,C++源程序的扩展名是CPP,VC会根据扩展名的不同调用不同的编译器来编译C或者CPP,C编译器不能识别C++的语法,所以不要搞错扩展名。
C++中头文件和源程序文件的扩展名分别是“.h”和“.cpp”;头文件在C语言家族程序中应用十分广泛。一般来说,每个C++/C程序通常由一个头文件( files)和定义文件组成。
第一个字母是cpp,所以C++源文件的扩展名是.cpp。
C++ 源代码文件的常见扩展名是 .cpp。在 C++ 编程中,源代码通常保存在扩展名为 .cpp 的文本文件中。这些文件包含 C++ 编程语言的源代码,可以使用文本编辑器或除 .cpp 扩展名外,还有其他与 C++ 源代码相关的扩展名。
C++源程序文件的扩展名是什么?
VC++6.0项目文件的扩展名是cpp,CPP是编程语言C++的另一种形式,cpp是用C++编写的源代码文件的后缀(*.cpp),对类的支持很强,可以让它写出更好的程序。C++头文件的后缀是(*.h),主要功能是
C++中头文件和库文件的扩展名是什么?C++头文件的扩展名是“.h”,C++库文件的扩展名是“.lib”
第一个字母是cpp,所以C++源文件的扩展名是.cpp。
C++中头文件和源程序文件的扩展名分别是“.h”和“.cpp”;头文件在C语言家族程序中应用十分广泛。一般来说,每个C++/C程序通常由一个头文件( files)和定义文件组成。
C++ 源代码文件的常见扩展名是 .cpp。在 C++ 编程中,源代码通常保存在扩展名为 .cpp 的文本文件中。这些文件包含 C++ 编程语言的源代码,可以使用文本编辑器或除 .cpp 扩展名外,还有其他与 C++ 源代码相关的扩展名。
在C++中,头文件扩展名是.h。源文件是.cpp。静态库文件是.lib。应该是.cpp。编译后是.obj。
在C++98标准之后,C标准库通过增加首字母c转换为C++命名空间头文件。例如stdio.h与++中的stdio.h和c中的stdio.h转换为不同的文件。在std的命名空间下重新声明stdio.h中的函数声明。它是接口调用的头文件….它是C++独有的。在引入命名空间后,.h逐渐被废除。
C语言源程序的扩展名是“.c”,由C语言组成的指令序列称为C源程序,源程序文件的后缀为“.c”。注意:在大多数操作系统中,C源代码文件后缀的大小写无所谓,如“index.C”和“index.c”指的是同一个文件;但有经验的程序员通常使用小写字母。会有特定的后缀。例如C++的源代码文件的后缀为“.cpp”;的源代码文件的后缀为“.py”;而C的源代码文件的后缀为“.C”。结构特点:1.C语言源程序可以由一个或多个源文件组成。2.每个源文件可以由一个或多个函数组成。3.一个源程序不管由多少个文件组成,有且只能有一个主函数,即main函数。 4.源程序中可以有预处理命令(命令只是其中一种),预处理命令通常应该放在源文件或源程序的开头。 5.每个注意,每个语句都必须以分号结束。但是,预处理命令、函数头和花括号“}”之后不能加分号。 6.标识符和关键字之间必须至少加一个空格以表示分隔。如果有明显的分隔符,则不需要空格来分隔。
在操作系统中,C语言源程序的后缀为.c。扩展信息(源程序与代码介绍):源程序是指一系列能够被人类读懂的计算机语言指令,现代编程语言中,源代码可以写成 源文件是以易于阅读和识别的格式存储的文件。目前很多程序主要使用高级语言进行开发,对执行效率有要求的部分用低级语言编写,以达到开发效率和运行效率之间的折衷。
C++对于源代码并没有明确的定义,但大家普遍认为C++的默认扩展名是cpp。这个说法的由来是,C++是C的一个扩展,由于C语言中的加法符号是++,所以新语言就被命名为C++。Plus的英文发音是Plus,所以标准的英文名称是C Plus Plus。首字母是cpp,所以C++源文件的扩展名是.cpp。
GHOST文件的后缀名为.Gho,Gho是Ghost工具软件的镜像文件存储扩展名,Gho文件中包含了Ghost软件备份的硬盘分区或者整个硬盘的全部文件信息。*.gho文件可以直接安装到系统上,不需要解压。Ghost可以提供系统的完整备份与恢复,支持的磁盘文件系统格式包括FAT、FAT32、NTFS、ext2、ext3、linux swap等,还可以对不支持的分区进行逐扇区的完整备份。Ghost分为Ghost(在DOS下运行)和(在下运行)两个版本,这两个版本都有统一的界面,可以实现同样的功能,但是不能恢复操作系统所在的分区,所以使用恢复系统分区可以从硬盘、光盘、U盘、移动硬盘进入PE系统启动电脑运行。Ghost一键版没有安装版的权限。公司安装电脑,建议使用安装版。
如果只生成一个文件,那么本题答案为B。编译()后生成目标文件,后缀为:.obj。也就是机器码。然后链接器()连接生成可执行文件,后缀为:.exe。最后运行命令(go),直接运行.exe文件。扩展信息:简单的说,编译器就是把“一种语言(通常是高级语言)”翻译成“另一种语言(通常是低级语言)”的程序。现代编译器的主要工作流程:源代码(代码)→预处理器()→编译器()→目标代码(代码)→链接器()→可执行程序()高级计算机语言便于人们编写、阅读和维护。机器语言是计算机能直接解释运行的。编译器以汇编或高级计算机语言源程序()作为输入,将其翻译成与目标语言()机器码等价的程序。源代码通常是高级语言(High-level),例如C、C++、Java、中文编程,或者汇编语言。目标是机器语言的目标代码,有时也叫机器码。对于C#、VB等高级语言,编译器此时的作用是将源代码()编译为通用中间语言(MSIL/CIL)的字节码()。最后运行时,经过通用语言运行库的转换,编程最终可以直接由CPU计算出机器码()。参考:百度百科-编辑
C语言源文件的后缀为.c,编译后的文件后缀为.obj,链接后的可执行文件的后缀为.exe,源文件的后缀只是为了表明该文件包含某种语言的代码(例如C语言代码就存放在.c文件中),这样便于程序员区分、编译器识别,并且不会导致文件内部格式的改变。它是一种层次结构清晰的C语言,程序可以采用模块化的方式编写,非常有利于程序的调试。C语言的处理和表达能力非常强大,依靠非常全面的运算符和多样的数据类型,可以很方便地完成各种数据结构的构建,并且可以直接寻址内存、通过指针类型直接操作硬件,因此既可以用来开发系统程序,也可以用来开发应用软件。C语言是通用性最强的计算机程序编辑语言,它不仅能发挥高级编程语言的功能,还兼具汇编语言的优点。
Java 源代码动态编译、类加载和代码执行(Java 8)
Java 的一个重要特性是动态的类加载机制。通过在运行时动态地加载类,Java 程序可以实现很多强大的功能。下面通过一个具体的实例来说明 Java 程序中,如何动态地编译 Java 源代码、加载类和执行类中的代码。这里的代码示例适用的版本是 Java 8。
示例所实现的功能很简单,就是对表达式求值。输入的是类似 1 + 1 或 3 * (2 + 3) 这样的表达式,返回的是表达式的值。示例的做法是动态创建一个 Java 源文件,编译该文件生成 class 文件,加载 class 文件之后再执行。比如,需要求值的表达式是 1 + 1,那么所生成的 Java 源文件如下所示,其中 1 + 1 的部分是动态的。
我们只需要编译该源文件,加载编译之后的 class 文件,再通过反射 API 来调用其中的 calculate 方法就可以得到表达式求值的结果。
第一步是动态生成 Java 源代码并编译。生成 Java 源代码比较简单,直接用字符串连接就可以了。当然了,在生成逻辑比较复杂时,推荐的做法是使用字符串模板引擎,如 Handlebars。在下面的代码中,getJavaSource 方法生成 Java 源代码,compile 方法进行编译。
在进行编译的时候,使用的是 JDK 标准的 JavaCompiler 接口。从源代码字符串中创建了一个 JavaFileObject 对象作为编译时的源代码单元。编译时的选项 -d 指定了编译结果的输出路径,这里是一个临时文件夹。compile 方法的返回值是一个 Pair 对象,包含了 class 文件的路径,以及随机生成的 Java 包的名称。
上面的代码用到了一个帮助类 StringContentJavaFileObject,表示从字符串创建的 JavaFileObject 对象。
编译完成之后的第二步是动态加载类。这一步并没有实现自定义的类加载器,而且使用内置的系统类加载器。系统类加载器通过 ClassLoader.getSystemClassLoader() 方法来获取。系统类加载器在 classpath 上查找类。这里用了一个比较 hack 的技巧来动态修改系统类加载器的 classpath。
在下面的代码中,ClasspathUpdater 的 addPath 方法可以把一个 Path 对象表示的路径,添加到系统类加载器的查找路径中。这是因为系统类加载器自身是 URLClassLoader 类型的加载器,其中的 addURL 方法可以添加新的查找路径。只不过 addURL 方法是 protected,这里通过反射 API 来进行调用。
上面介绍的 ClasspathUpdater 类中的使用技巧,只对 Java 8 生效。在 Java 9 引入模块系统时,对系统类加载器进行了修改。系统类加载器被替换成了应用类加载器。应用类加载器不再是 URLClassLoader 类型了,就不能使用这个技巧了。
最后一步就是执行动态加载的 Java 类。这一步比较简单,只需要用 Class.forName 方法来查找 Java 类,再找到对应的 Method 对象,直接调用即可。下面的代码给出了示例。
最后把整个流程串起来。在下面的代码中,需要求值的表达式是 (1 + 1) * 3 / 5.0。首先调用 DynamicCompilation.compile 方法进行动态编译,得到 class 文件的路径和完整的类名。class 文件的路径通过 ClasspathUpdater.addPath 方法添加到 classpath 中。完整的类名则传递给 Invoker.invoke 方法来执行。最后输出的结果是表达式的值。
本文作者及来源:Renderbus瑞云渲染农场https://www.renderbus.com
文章为作者独立观点不代本网立场,未经允许不得转载。