摘要:Java是一门面向对象的编程语言,自1995年5月23日问世以来,已有十数版更新发布。只有了解Java历史,才可能了解Java的前世今生,把握Java的未来。作为一名初学者,有必要系统了解Java各个版本的发布历史及其新的不同特性,本文系统研究回顾了Java标准版本JavaSE ( Java Standard Edition, JavaSE)从5.0至14.0各个版本相比上一版本的新特性变化。报告内容可以作为JavaSE初学者的系统性学习资料,报告内容也已发布在个人CSDN上,与同为初学者的用户共同学习,以期大家对Java的发展历史拥有比较全面的了解。
关键词:JavaSE历史版本;新特性;初学者
1引言
正如Java白皮书所写,Java是一门简单的、面向对象的、分布式、解释、健壮、安全、结构中立、可移植、高效能、多线程、动态的语言[1]。NASA的科学家们正是通过一个名为Maestro的Java程序来控制勇气号,这个过程像玩游戏一样简单,这也足以说明Java程序使用的广泛性和简单性[2]。
Java自1995年5月23日发布以来,历经十数版本,每次更新都会带来一些新特性,然而在其不断更新的过程中,Java的用户越来越多,依然在各大网站评比某年最流行的编程语言的的排行中位数前列,这些背后依赖的便是Java语言的基本特性。具体来说,简单性就是指Java剔除了C++中很少使用、易于混淆、难以理解的特性,例如头文件、指针、结构、联合、操作符重载等,所开发软件均能在小型机器上运行。面向对象是指Java面向数据和目标对象本身,而非实现操作的“工具”。分布式是指Java程序本身有丰富的例程库,能够通过URL打开和访问网络上的对象。健壮性指Java能够在运行前就能检查出许多其他编程语言在运行后才能发现的bug,进行早期问题检测,节约时间。安全性是指Java能够防范各种病毒和试图篡改的代码的攻击。结构中立指编译器生成一个体系结构中立的目标文件格式,这是一种编译过的代码,只要有Java 运行时系统,这些编译后的代码可以在许多处理器上运行。可移植性指Java基本数据类型和大小都有明确规定,拥有可移植的接口。高性能指在运行时字节码能够动态翻译成特定CPU的机器码。此外,Java可以多线程工作,Java库中可以动态自由修改添加新方法,对客户端没有影响[3]。正是由于上述特性,Java以其独特的风格获得了众多程序员的青睐。
大量的应用软件和Web节点由Java开发或者用到Java,可以说,从游戏控制台到科学超级计算机,从手机到互联网,Java 无处不在[4]!而不断更新发布的JavaSE版本也为这些应用的开发增添新色,作为一名初学者,有必要详细了解一下各版本JavaSE之间的区别,对于后续学习也能起到开门见山、奠定基础的作用!
2 JavaSE各版本发布及其新特性变化
自诞生以来,Java历经十数版而存活,并且被广泛使用至今。关于Java,一个比较有趣的事情就是Java自身的命名方式的变化。从1996年1月23日至1999年4月8日,Java从JDK1.0更新至JDK1.1.8,在1998年12月8日JAVA2企业版J2EE发布,1999年6月,SUN公司发布Java三个版本:标准版、企业版和微型版(J2SE、J2EE、J2ME),从1998年12月4日至2003年6月26日,JavaSE经历了J2SE1.2至J2SE1.4.2的版本变化。2004年9月30日,J2SE1.5发布,具有里程碑意义,为显示这个版本的重要性,将要发布的J2SE1.5更名为J2SE5.0,从而也正式结束了“1”的时代。2005年6月,Java取消各种版本号中的数字“2”,曾经的J2EE更名为Java EE, J2SE更名为Java SE,J2ME更名为Java ME,同时SUN公司公开JavaSE6.0,J2SE1.5也变为JavaSE5.0,这种命名方式持续下去,一直到2019年JavaSE14.0.
JavaSE从JavaSE5.0开始,至JavaSE14.0,因此对于初学者我们有必要从5.0开始详细了解一下每次发布新版本时,其与以前发布版本相比的新特性,包括其新增或改进方面的特性。
2.1JavaSE5.0发布时间及其新特性
2004年9月30日发布。
主要新特性体现在以下几个方面:
(1)自动装箱与拆箱。自动装箱指需要一种类型对象时,该基本类型就会自动封装到与它相同类型的包装中。自动拆箱指每需要一个值时,被装箱对象中值就会被自动提取出来,而不需去调intValue()和doubleValue()方法。(2)枚举。提取集合中的对象元素。枚举类型使代码更具可读性,理解清晰,易于维护。枚举类型是强类型的,从而保证了系统安全性。而以类的静态字段实现的类似替代模型,不具有枚举的简单性和类型安全性。枚举有简单用法和内置复杂用法(Java内置)。(3)静态导入。通过使用 import static,可不用指定Constants类名而直接使用静态成员,包括静态方法。import xxxx 和 import static xxxx的区别是前者一般导入的是类文件如import Java.util.Scanner;后者一般是导入静态的方法,import static Java.lang.System.out。(4)可变参数(Varargs)。可变参数的简单语法格式:methodName([argumentList],dataType... argumentName)。(5)内省(Introspector)。内省是Java语言对Bean类属性、事件的一种缺省处理方法。通过类Introspector来获取某个对象的BeanInfo信息,接着通过BeanInfo来获取属性的描述器(PropertyDescriptor),通过这个属性描述器就可以获取某个属性对应的getter/setter方法,最后可通过反射机制来调用这些方法。(6)泛型(Generic)。C++ 通过模板技术可以指定集合的元素类型,而Java在1.5之前一直没有相对应的功能。一个集合可以放任何类型的对象,从该集合里面拿对象的时候我们也不得不对他们进行强制类型转换操作。而JavaSE5.0新增了泛型,它允许指定集合里元素的类型,这样方便了编译时类型检查。(7)For-Each循环。For-Each循环的加入简化了集合的遍历过程。(8) 输入控制台。在Java.lang.Scanner类,可以实现从控制台直接读取数据。(9)格式化输出、Unicode编码、构建字符串的新方法StringBuilder。
2.2 JavaSE6.0发布及其新特性
2006年12月11日发布。
主要新特性体现在以下几个方面:
(1)存取权限控制方法。JavaSE5.0中提供的存取权限直接用于存取对象时可能导致File类方法失败,JavaSE6.0提供了6种新方法以便修改路径名的存取权限,具体包括public boolean setExecutable(Boolean executable,Boolean ownerOnly)、public oolean setReadable( oolean readable, oolean ownerOnly)等。(2)桌面集成。三个新特征是:Splash屏幕支持(它让应用程序在启动过程中显示Splash屏幕),系统托盘支持(它让应用程序把图标,提示窗信息和弹出菜单添加到系统托盘),和一组新的桌面API。详细方法查找官方资料。(3)支持脚本语言。JavaSE6.0加入了对Script(JSR223)的支持。这是一个脚本框架,提供了让脚本语言来访问Java内部的方法。可以在运行的时候找到脚本引擎,然后调用这个引擎去执行脚本。这个脚本API允许为脚本语言提供Java支持。另外,Web Scripting Framework允许脚本代码在任何的Servlet容器(例如Tomcat)中生成Web内容。(4)JDBC4.0. 借助Mustang中包含的Java SE Service Provider机制,Java开发人员不再需要使用像Class.forName()这样的代码显式地加载JDBC驱动程序,就能注册JDBC驱动程序。通过在调用DriverManager.getConnection()方法时自动定位合适的驱动程序,DriverManager类可以做到这一点。这个功能是向后兼容的,所以无需修改现有的JDBC代码。在访问关系数据库的Java应用程序中,通过最小化我们需要编写的“模板”代码,JDBC 4.0还改善了开发人员体验。它还提供实用程序类,以改进JDBC驱动程序的注册和卸载机制,以及管理数据源和连接对象。(5)Java Compiler API。可以用JDK6 的Compiler API(JSR 199)去动态编译Java源文件,Compiler API结合反射功能就可以实现动态的产生Java代码并编译执行这些代码,有点动态语言的特征。这个特性对于某些需要用到动态编译的应用程序相当有用。(6)可插拔注解。(7) 增加对Native PKI(Public Key Infrastructure), Java GSS(Generic Security Service),Kerberos和LDAP(Lightweight Directory Access Protocol)支持。(8)集成web services。
2.3 JavaSE7.0发布及其新特性
2011年7月8日发布。
主要新特性体现在以下几个方面:
(1)switch语句块中允许以字符串作为分支条件。(2)在创建泛型对象时应用类型推断。(3)在一个语句块中捕获多种异常。(4)支持动态语言。(5)支持try-with-resources(在一个语句块中捕获多种异常)。(6)引入Java NIO.2开发包。(7)数值类型可以用二进制字符串表示,并且可以在字符串表示中添加下划线。(8)钻石型语法(在创建泛型对象时应用类型推断)。(9)null值自动处理。
2.4 JavaSE8.0发布及其新特性
2014年3月 18日发布。
主要新特性体现在以下几个方面:
(1)Lambda 表达式。Lambda允许把函数作为一个方法的参数(函数作为参数传递到方法中)。(2)方法引用。方法引用提供了非常有用的语法,可以直接引用已有Java类或对象(实例)的方法或构造器。与lambda联合使用,方法引用可以使语言的构造更紧凑简洁,减少冗余代码。(3)默认方法。默认方法就是一个在接口里面有了一个实现的方法。(4)新工具。新的编译工具,如:Nashorn引擎 jjs、类依赖分析器jdeps。(5)Stream API 。新添加的Stream API(Java.util.stream)把真正的函数式编程风格引入到Java中。(6)Date Time API 。加强对日期与时间的处理。(7)Optional类 。Optional 类已经成为Java8类库的一部分,用来解决空指针异常。(8)Nashorn, JavaScript 引擎。Java 8提供了一个新的Nashorn Javascript引擎,它允许我们在JVM上运行特定的Javascript应用。
2.5 JavaSE9.0发布及其新特性
2017年9月22日发布。
主要新特性体现在以下几个方面:
(1)模块系统。模块是一个包的容器,Java 9 最大的变化之一是引入了模块系统(Jigsaw 项目)。(2)REPL (JShell)。交互式编程环境。(3)HTTP 2 客户端。HTTP/2标准是HTTP协议的最新版本,新的 HTTPClient API 支持 WebSocket 和 HTTP2 流以及服务器推送特性。(4)改进的 Javadoc。Javadoc 现在支持在 API 文档中的进行搜索。另外,Javadoc 的输出现在符合兼容 HTML5 标准。(5)多版本兼容 JAR 包。多版本兼容 JAR 功能能让你创建仅在特定版本的 Java 环境中运行库程序时选择使用的 class 版本。(6)集合工厂方法。List,Set 和 Map 接口中,新的静态工厂方法可以创建这些集合的不可变实例。(7)私有接口方法。在接口中使用private私有方法。我们可以使用 private 访问修饰符在接口中编写私有方法。(8)进程 API。改进的 API 来控制和管理操作系统进程。引进 Java.lang.ProcessHandle 及其嵌套接口 Info 来让开发者逃离时常因为要获取一个本地进程的 PID 而不得不使用本地代码的窘境。(9)改进的 Stream API。改进的 Stream API 添加了一些便利的方法,使流处理更容易,并使用收集器编写复杂的查询。(10)改进 try-with-resources。如果你已经有一个资源是 final 或等效于 final 变量,您可以在 try-with-resources 语句中使用该变量,而无需在 try-with-resources 语句中声明一个新变量。(11)改进的弃用注解@Deprecated。注解@Deprecated可以标记Java API状态,可以表示被标记的API将会被移除,或者已经破坏。(12)改进钻石操作符(Diamond Operator) 。匿名类可以使用钻石操作符(Diamond Operator)。(13)改进 Optional 类。Java.util.Optional 添加了很多新的有用方法,Optional 可以直接转为 stream。(14)多分辨率图像 API。定义多分辨率图像API,开发者可以很容易的操作和展示不同分辨率的图像了。(15)改进的 CompletableFuture API。CompletableFuture 类的异步机制可以在ProcessHandle.onExit方法退出时执行操作。(16)轻量级的JSON API。内置了一个轻量级的JSON API。(17)响应式流(Reactive Streams) API。Java 9中引入了新的响应式流 API 来支持 Java 9 中的响应式编程。
2.6 JavaSE10.0发布及其新特性
2018年3月21日发布。
主要新特性体现在以下几个方面:
(1)var局部变量类型推断。(2)将原来用Mercurial管理的众多 JDK仓库代码,合并到一个仓库中,简化开发和管理过程。(3)统一的垃圾回收接口。(4) G1垃圾回收器的并行完整垃圾回收,实现并行性来改善最坏情况下的延迟。(5)应用程序类数据 (AppCDS) 共享,通过跨进程共享通用类元数据来减少内存占用空间,和减少启动时间。(6) ThreadLocal握手交互。在不进入到全局 JVM 安全点 (Safepoint) 的情况下,对线程执行回调。优化可以只停止单个线程,而不是停全部线程或一个都不停。(7)移除 JDK 中附带Javah工具。可以使用 Javac -h 代替。(8)使用附加的 Unicode 语言标记扩展。(9)能将堆内存占用分配给用户指定的备用内存设备。(10)使用Graal基于Java的编译器,可以预先把Java代码编译成本地代码来提升效能。(11)在OpenJDK中提供一组默认的根证书颁发机构证书。开源目前 Oracle 提供的的 Java SE 的根证书,这样 OpenJDK 对开发人员使用起来更方便。(12)基于时间定义的发布版本,即上述提到的发布周期。版本号为\$FEATURE.\$INTERIM.\$UPDATE.\$PATCH,分别是大版本,中间版本,升级包和补丁版本。
2.7 JavaSE11.0发布及其新特性
2018年9月25日发布。
(1)Nest-Based访问控制。(2)动态类文件常量。(3)改善Aarch64 intrinsic。(4)无操作垃圾收集器。(5)消除Java EE和CORBA模块。(6)HTTP客户端(标准)。(7)局部变量的语法λ参数。(8)Curve25519和Curve448关键协议。(9)Unicode 10。(10)飞行记录器。(11)ChaCha20和Poly1305加密算法。(12)发射一列纵队源代码程序。(13)低开销堆分析。(14)传输层安全性(Transport Layer Security,TLS)1.3。(15)动作:一个可伸缩的低延迟垃圾收集器 (实验)。(16)反对Nashorn JavaScript引擎。(17)反对Pack200工具和API
2.8 JavaSE12.0发布及其新特性
2019年3月发布。
主要新特性体现在以下几个方面:
(1)JDK 12版本包含对Unicode 11.0.0的支持。684个新字符、11个新块、7个新脚本。(2)在Linux上的posix_spawn选项。作为在Linux上启动进程的另一种方法,jdk.lang.Process.launchMechanism可以将该属性设置为POSIX_SPAWN。POSIX_SPAWN
减轻了产生子进程时的罕见病理情况,但尚未经过充分测试。(3)JVM常量API。新软件包Java.lang.invoke.constant引入了一个API,用于对类文件和运行时工件的名义描述进行建模,特别是可以从常量池中加载的常量。(4)支持紧凑型数字格式。NumberFormat增加了对以紧凑格式格式化数字的支持。紧凑的数字格式是指数字的简短形式或易于理解的形式。(5) ZGC并发类卸载。Z垃圾收集器现在支持类卸载。通过卸载未使用的类,可以释放与这些类相关的数据结构,从而减少应用程序的总体占地面积。(6)Java堆的老一代对备用内存设备分配。G1和Parallel GC中的这一实验性功能允许他们在替代存储设备(例如NV-DIMM内存)上分配旧版Java堆。(7)禁止并允许Java.security.manager系统属性的选项 。新的“ disallow”和“ allow”令牌选项已添加到Java.security.manager系统属性。在JDK实现中,如果Java虚拟机以系统属性Java.security.manager设置为“ disallow”开始,则该System.setSecurityManager方法不能用于设置安全管理器,并且会抛出UnsupportedOperationException。“禁止”选项可以提高从未设置安全管理器的应用程序的运行时性能。(8)groupname选项添加到在keytool密钥对生成。(9)新的Java Flight Recorder(JFR)安全事件。(10)自定义PKCS12密钥库生成、ChaCha20和Poly1305 TLS密码套件、支持krb5.conf中dns_canonicalize_hostname。(11)jdeps -print-模块的DEP报告传递的依赖性、开关表达式(预览) 。
2.9 JavaSE13.0发布及其新特性
2019年9月发布。
主要新特性体现在以下几个方面:
(1) 添加了FileSystems.newFileSystem(Path,Map
2.10 JavaSE14.0发布及其新特性
2020年3月发布。
主要新特性体现在以下几个方面:
(1)会计货币格式支持。可以通过NumberFormat.getCurrencyInstance(Locale)使用“ u-cf-account” Unicode区域设置扩展名来获得具有记帐样式的货币格式实例,其中在某些区域设置中用括号将金额格式化。例如在中Locale.US,它将格式化为“ ($3.27)”而不是“ -$3.27”。(2)在JDK 14中,“ 记录(JEP 359)”预览功能添加了一个新类Java.lang.Record
。该Java.lang
软件包是按需隐式导入的import Java.lang.*
。如果现有源文件中的代码按需导入某些其他程序包,例如,import com.myapp.*;
并且该其他程序包声明了一个名为的类型Record
,则引用该类型的现有源文件中的代码将不进行更改而不会编译。(3)阐明ReadableByteChannel.read()的规范和相关方法。(4)ZGC在Windows 和MacOS上的变化。(5)并行GC改进。并行GC已采用与其他收集器相同的任务管理机制来调度并行任务,这可能会显着提高性能。(5)NUMA感知内存分配。G1垃圾收集器现在尝试跨垃圾收集在年轻一代的同一NUMA节点上分配并保留对象。这类似于并行GC NUMA意识。(6)JFR事件流。(7)Santuario库已更新至版本2.1.4。(8)允许默认情况下调用可发现的Javac插件。现在,如果未Javac在从命令行传递的选项或optionsAPI调用的参数中显式启动Javac“ plugins”,则默认情况下可以选择启动它。通过实现Plugin.isDefault()return 方法可以启用此行为true。(9)SAX ContentHandler的用于处理XML声明的新方法。declaration添加了一个新方法SAX ContentHandler来接收XML声明的通知。通过实现此方法,应用程序可以完全按照输入文档中的声明接收版本,编码和独立属性的值。
通过总结JavaSE5.0至JavaSE14.0的变化,可以看出,每一版发布都有其亮点,增加新的功能,增强上一版的功能,或者删除部分过时功能,都是新版发布的主要内容。作为初学者,通过总结以上内容,可以体会整个JavaSE发展的过程,更好地理解今后编程可能涉及到的上述内容。