JDK1.5-1.10各个版本的新特性
JDK1.5新特性:
1.自动装箱与拆箱:
2.枚举
3.静态导入,如:import staticjava.lang.System.out
4.可变参数(Varargs)
5.内省(Introspector),主要用于操作JavaBean中的属性,通过getXxx/setXxx。一般的做法是通过类Introspector来获取某个对象的BeanInfo信息,然后通过BeanInfo来获取属性的描述器(PropertyDescriptor),通过这个属性描述器就可以获取某个属性对应的getter/setter方法,然后我们就可以通过反射机制来调用这些方法。
6.泛型(Generic)(包括通配类型/边界类型等)
7.For-Each循环
8.注解
9.协变返回类型:实际返回类型可以是要求的返回类型的一个子类型
JDK1.6新特性:
1. AWT新增加了两个类:Desktop和SystemTray,其中前者用来通过系统默认程序来执行一个操作,如使用默认浏览器浏览指定的URL,用默认邮件客户端给指定的邮箱发邮件,用默认应用程序打开或编辑文件(比如,用记事本打开以txt为后缀名的文件),用系统默认的打印机打印文档等。后者可以用来在系统托盘区创建一个托盘程序
2.使用JAXB2来实现对象与XML之间的映射,可以将一个Java对象转变成为XML格式,反之亦然
3. StAX,一种利用拉模式解析(pull-parsing)XML文档的API。类似于SAX,也基于事件驱动模型。之所以将StAX加入到JAXP家族,是因为JDK6中的JAXB2和JAX-WS 2.0中都会用StAX。
4.使用Compiler API,动态编译Java源文件,如JSP编译引擎就是动态的,所以修改后无需重启服务器。
5.轻量级Http Server API,据此可以构建自己的嵌入式HttpServer,它支持Http和Https协议。
6.插入式注解处理API(PluggableAnnotation Processing API)
7.提供了Console类用以开发控制台程序,位于java.io包中。据此可方便与Windows下的cmd或Linux下的Terminal等交互。
8.对脚本语言的支持如: ruby,groovy, javascript
9.Common Annotations,原是J2EE 5.0规范的一部分,现在把它的一部分放到了J2SE 6.0中
10.嵌入式数据库 Derby
JDK1.7 新特性
1.对Java集合(Collections)的增强支持,可直接采用[]、{}的形式存入对象,采用[]的形式按照索引、键值来获取集合中的对象。如:
List<String>list=[“item1”,”item2”];//存
Stringitem=list[0];//直接取
Set<String>set={“item1”,”item2”,”item3”};//存
Map<String,Integer> map={“key1”:1,”key2”:2};//存
Intvalue=map[“key1”];//取
2.在Switch中可用String
3.数值可加下划线用作分隔符(编译时自动被忽略)
4.支持二进制数字,如:int binary= 0b1001_1001;(二进制的前缀0b,后缀B,八进制的前缀0,后缀Q,十六进制的前缀0x,后缀H)
5.简化了可变参数方法的调用
6.调用泛型类的构造方法时,可以省去泛型参数,编译器会自动判断。
7.Boolean类型反转,空指针安全,参与位运算
8.char类型的equals方法: booleanCharacter.equalsIgnoreCase(char ch1, char ch2)
9.安全的加减乘除: Math.safeToInt(longv); Math.safeNegate(int v); Math.safeSubtract(long v1, int v2);Math.safeMultiply(int v1, int v2)……
10 .Map集合支持并发请求,注HashTable是线程安全的,Map是非线程安全的。但此处更新使得其也支持并发。另外,Map对象可这样定义:Map map = {name:"xxx",age:18};
JDK1.8新特性
1.接口的默认方法:即接口中可以声明一个非抽象的方法做为默认的实现,但只能声明一个,且在方法的返回类型前要加上“default”关键字。
2. Lambda 表达式:是对匿名比较器的简化,如:
Collections.sort(names,(String a, String b) -> {
returnb.compareTo(a);
});
对于函数体只有一行代码的,你可以去掉大括号{}以及return关键字。如:
Collections.sort(names,(String a, String b) -> b.compareTo(a));
或:Collections.sort(names, (a, b) -> b.compareTo(a));
3. 函数式接口:是指仅仅只包含一个抽象方法的接口,要加@FunctionalInterface注解
4. 使用 :: 关键字来传递方法或者构造函数引用
5.多重注解
6.还增加了很多与函数式接口类似的接口以及与Map相关的API等……
jdk1.9新特性
1、Java 平台级模块系统
当启动一个模块化应用时, JVM 会验证是否所有的模块都能使用,这基于 `requires` 语句——比脆弱的类路径迈进了一大步。模块允许你更好地强制结构化封装你的应用并明确依赖。
2. Linking
当你使用具有显式依赖关系的模块和模块化的 JDK 时,新的可能性出现了。你的应用程序模块现在将声明其对其他应用程序模块的依赖以及对其所使用的 JDK 模块的依赖。为什么不使用这些信息创建一个最小的运行时环境,其中只包含运行应用程序所需的那些模块呢? 这可以通过 Java 9 中的新的 jlink 工具实现。你可以创建针对应用程序进行优化的最小运行时映像而不需要使用完全加载 JDK 安装版本。
3. JShell : 交互式 Java REPL
许多语言已经具有交互式编程环境,Java 现在加入了这个俱乐部。您可以从控制台启动 jshell ,并直接启动输入和执行 Java 代码。 jshell 的即时反馈使它成为探索 API 和尝试语言特性的好工具。
4. 改进的 Javadoc
Javadoc 现在支持在 API 文档中的进行搜索。另外,Javadoc 的输出现在符合兼容 HTML5 标准。此外,你会注意到,每个 Javadoc 页面都包含有关 JDK 模块类或接口来源的信息。
5. 集合工厂方法
通常,您希望在代码中创建一个集合(例如,List 或 Set ),并直接用一些元素填充它。 实例化集合,几个 “add” 调用,使得代码重复。 Java 9,添加了几种集合工厂方法:
Set<Integer> ints = Set.of(4,5,3);
List<String> strings = List.of("a","v");
除了更短和更好阅读之外,这些方法也可以避免您选择特定的集合实现。 事实上,从工厂方法返回已放入数个元素的集合实现是高度优化的。这是可能的,因为它们是不可变的:在创建后,继续添加元素到这些集合会导致 “UnsupportedOperationException” 。
6. 改进的 Stream API
长期以来,Stream API 都是 Java 标准库最好的改进之一。通过这套 API 可以在集合上建立用于转换的申明管道。在 Java 9 中它会变得更好。Stream 接口中添加了 4 个新的方法:dropWhile, takeWhile, ofNullable。还有个 iterate 方法的新重载方法,可以让你提供一个 Predicate (判断条件)来指定什么时候结束迭代:
IntStream.iterate(1, i -> i < 100, i -> i + 1).forEach(System.out::println);
第二个参数是一个 Lambda,它会在当前 IntStream 中的元素到达 100 的时候返回 true。因此这个简单的示例是向控制台打印 1 到 99。
除了对 Stream 本身的扩展,Optional 和 Stream 之间的结合也得到了改进。现在可以通过 Optional 的新方法 `stram` 将一个 Optional 对象转换为一个(可能是空的) Stream 对象:
Stream<Integer> s = Optional.of(1).stream();
在组合复杂的 Stream 管道时,将 Optional 转换为 Stream 非常有用。
7. 私有接口方法
使用 Java 9,您可以向接口添加私有辅助方法来解决此问题:
publicinterface
MyInterface {
voidnormalInterfaceMethod();
defaultvoid
interfaceMethodWithDefault() { init(); }
defaultvoid
anotherDefaultMethod() { init(); }
// This method is not part of the public API exposed by MyInterface
privatevoid
init() { System.out.println("Initializing"); }
}
如果您使用默认方法开发 API ,那么私有接口方法可能有助于构建其实现。
8. HTTP/2
Java 9 中有新的方式来处理 HTTP 调用。这个迟到的特性用于代替老旧的 `HttpURLConnection` API,并提供对 WebSocket 和 HTTP/2 的支持。注意:新的 HttpClient API 在 Java 9 中以所谓的孵化器模块交付。也就是说,这套 API 不能保证 100% 完成。不过你可以在 Java 9 中开始使用这套 API:
HttpClient client = HttpClient.newHttpClient();
HttpRequest req =
HttpRequest.newBuilder(URI.create("http://www.google.com"))
.header("User-Agent","Java")
.GET()
.build();
HttpResponse<String> resp = client.send(req, HttpResponse.BodyHandler.asString());
HttpResponse<String> resp = client.send(req, HttpResponse.BodyHandler.asString());
除了这个简单的请求/响应模型之外,HttpClient 还提供了新的 API 来处理 HTTP/2 的特性,比如流和服务端推送。
9. 多版本兼容 JAR
我们最后要来着重介绍的这个特性对于库的维护者而言是个特别好的消息。当一个新版本的 Java 出现的时候,你的库用户要花费数年时间才会切换到这个新的版本。这就意味着库得去向后兼容你想要支持的最老的 Java 版本 (许多情况下就是 Java 6 或者 7)。这实际上意味着未来的很长一段时间,你都不能在库中运用 Java 9 所提供的新特性。幸运的是,多版本兼容 JAR 功能能让你创建仅在特定版本的 Java 环境中运行库程序时选择使用的 class 版本:
multirelease.jar
├── META-INF
│ └── versions
│ └── 9
│ └── multirelease
│ └── Helper.class
├── multirelease
├── Helper.class
└── Main.class
- 局部变量类型推断
- 将JDK多存储库合并为单储存库
- 垃圾回收接口
- 并行Full GC 的G1
- 应用数据共享
- 线程局部管控
- 移除Native-Header Generation Tool (javah)
- Unicode 标签扩展
- 备用内存设备上分配堆内存
- 基于实验JAVA 的JIT 编译器
- Root 证书
- 基于时间的版本控制
-
局部变量类型推断
很多人抱怨Java是一种强类型,需要引入大量的样板代码。甚至在这些情况下,给定好变量名,通常很清楚发生了什么,明显类型声明往往被认为是不必要的。许多流行的编程语言都已经支持某种形式的局部变量类型推断:如C++ (auto), C# (var), Scala (var/val), Go (declaration with :=)等。
JDK10 可以使用var作为局部变量类型推断标识符,此符号仅适用于局部变量,增强for循环的索引,以及传统for循环的本地变量;它不能使用于方法形式参数,构造函数形式参数,方法返回类型,字段,catch形式参数或任何其他类型的变量声明。
标识符var不是关键字;相反,它是一个保留的类型名称。这意味着var用作变量,方法名或则包名称的代码不会受到影响;但var不能作为类或则接口的名字(但这样命名是比较罕见的,因为他违反了通常的命名约定,类和接口首字母应该大写)。
参考一下示例:
var str = "ABC"; //根据推断为 字符串类型 var l = 10L;//根据10L 推断long 类型 var flag = true;//根据 true推断 boolean 类型 var flag1 = 1;//这里会推断boolean类型。0表示false 非0表示true var list = new ArrayList<String>(); // 推断 ArrayList<String> var stream = list.stream(); // 推断 Stream<String>
反编译class文件:
String str = "ABC"; long l = 10L; boolean flag = true; int flag1 = true; ArrayList<String> list = new ArrayList(); Stream<String> stream = list.stream();
从上面示例可以看出,当我们是用复杂的方法时,不需要特意去指定他的具体类型返回,可以使用var推断出正确的数据类型,这在编码中,可以大幅减少我们对方法返回值的探究。
将JDK多存储库合并为单存储库
为了简化和简化开发,将JDK多存储库合并到一个存储库中。多年来,JDK的完整代码已经被分解成多个存储库。在JDK9 中有八个仓库:root、corba、hotspot、jaxp、jaxws、jdk、langtools和nashorn。在JDK10中被合并为一个存储库。
虽然这种多存储库模型具有一些有点,但它也有许多缺点,并且在支持各种可取的源代码管理操作方面做得很差。特别是,不可能在相互依赖的变更存储库之间执行原子提交。例如,如果一个bug修复或RFE的代码现在同时跨越了jdk和hotspot 存储库,那么对于两个存储库来说,在托管这两个不同的存储库中,对两个存储库的更改是不可能实现的。跨多个存储库的变更是常见。
垃圾回收接口
这不是让开发者用来控制垃圾回收的接口;而是一个在 JVM 源代码中的允许另外的垃圾回收器快速方便的集成的接口。
垃圾回收接口为HotSpot的GC代码提供更好的模块化;在不影响当前代码的基础情况下,将GC添加到HotSpot变的更简单;更容易从JDK构建中排除GC。实际添加或删除GC不是目标,这项工作将使HotSpot中GC算法的构建时间隔离取得进展,但它不是完全构建时间隔离的目标。
并行Full GC 的G1
JDK10 通过并行Full GC,改善G1的延迟。G1垃圾收集器在JDK 9中是默认的。以前的默认值并行收集器中有一个并行的Full GC。为了尽量减少对使用GC用户的影响,G1的Full GC也应该并行。
G1垃圾收集器的设计目的是避免Full收集,但是当集合不能足够快地回收内存时,就会出现完全GC。目前对G1的Full GC的实现使用了单线程标记-清除-压缩算法。JDK10 使用并行化标记-清除-压缩算法,并使用Young和Mixed收集器相同的线程数量。线程的数量可以由-XX:ParallelGCThreads选项来控制,但是这也会影响用Young和Mixed收集器的线程数量。
应用数据共享
为了提高启动和内存占用,扩展现有的类数据共享(CDS)特性,允许将应用程序类放置在共享档案中。
- 通过在不同的Java进程间共享公共类元数据来减少占用空间。
- 提升启动时间。
- CDS允许将来自JDK的运行时映像文件($JAVA_HOME/lib/modules)的归档类和应用程序类路径加载到内置平台和系统类加载器中。
- CDS允许将归档类加载到自定义类加载器中。
-
线程局部管控
在不执行全局VM安全点的情况下对线程执行回调的方法。让它停止单个线程而不是全部线程。
移除Native-Header Generation Tool (javah)
JDK10 从JDK中移除了javah 工具。该工具已被JDK8 (JDK-7150368)中添加javac高级功能所取代。此功能提供了在编译java源代码时编写本机头文件的功能,从而无需使用单独的工具。
Unicode 标签扩展
JDK10 改善 java.util.Locale 类和相关的 API 以实现额外 BCP 47 语言标签的 Unicode 扩展。尤其以下扩展支持:
- cu:货币类型
- fw:一周的第一天
- rg:区域覆盖
- tz:时区
-
为支持以上扩展,JDK10对以下API进行更改:
- java.text.DateFormat::get*Instance:将根据扩展ca、rg或tz返回实例。
- java.text.DateFormatSymbols::getInstance:将根据扩展rg返回实例。
- java.text.DecimalFormatSymbols::getInstance:将根据扩展rg返回实例。
- java.text.NumberFormat::get*Instance:将根据nu或rg返回实例。
- java.time.format.DateTimeFormatter::localizedBy:将返回DateTimeFormatter 根据ca,rg或rz的实例。
- java.time.format.DateTimeFormatterBuilder::getLocalizedDateTimePattern:将根据rg返回String。
- java.time.format.DecimalStyle::of:将返回DecimalStyle根据nu或rg的实例。
- java.time.temporal.WeekFields::of:将返回WeekFields根据fw或rg的实例。
- java.util.Calendar::{getFirstDayOfWeek,getMinimalDaysInWeek}:将根据fw或rg返回值。
- java.util.Currency::getInstance:将返回Currency根据cu或rg返回实例。
- java.util.Locale::getDisplayName:将返回一个包含这些U扩展名的显示名称的字符串。
- java.util.spi.LocaleNameProvider:将为这些U扩展的键和类型提供新的SPI。
- 在多JVM部署中,某些JVM(如守护进程,服务等)的优先级低于其他JVM。与DRAM相比,NV-DIMM可能具有更高的访问延迟。低优先级进程可以为堆使用NV-DIMM内存,允许高优先级进程使用更多DRAM。
- 诸如大数据和内存数据库等应用程序对内存的需求不断增加。这种应用可以将NV-DIMM用于堆,因为与DRAM相比,NV-DIMM可能具有更大的容量,成本更低。
-
基于实验JAVA 的JIT 编译器
启用基于Java的JIT编译器Graal,将其用作Linux / x64平台上的实验性JIT编译器。Graal是一个基于Java的JIT编译器,它是JDK 9中引入的Ahead-of-Time(AOT)编译器的基础。使它成为实验性JIT编译器是Project Metropolis的一项举措,它是下一步是研究JDK的基于Java的JIT的可行性。
使Graal可用作实验JIT编译器,从Linux / x64平台开始。Graal将使用JDK 9中引入的JVM编译器接口(JVMCI)。Graal已经在JDK中,因此将它作为实验JIT将主要用于测试和调试工作。要启用Graal作为JIT编译器,请在java命令行上使用以下选项:
-XX:+UnlockExperimentalVMOptions -XX:+UseJVMCICompiler
Root 证书
在JDK中提供一组默认的root 认证权威(CA)证书。在Oracle的Java SE根CA程序中开源root证书,以使OpenJDK构建对开发人员更有吸引力,并减少这些构建和Oracle JDK构建之间的差异。
cacerts密钥存储库是JDK的一部分,它的目的是包含一组root证书,这些root证书可以用来在各种安全协议中使用的证书链中建立信任。然而,JDK源代码中的cacerts密钥库目前是空的。因此,诸如TLS之类的关键安全组件在OpenJDK构建中不会默认工作。为了解决这个问题,用户必须配置和填充cacerts密钥库,并使用一组root证书来记录,例如, JDK 9 release notes。
基于时间的版本控制
在JEP 223 引入的版本字符串方案比以往有了显著的改进,但是,该方案并不适合未来,现在Java SE平台和JDK的新版本严格按照六个月的节奏发布。JEP 223方案的主要困难在于发行版的版本号对于其前身的重要性和兼容性进行了编码。然而,在基于时间发布模式中,这些品质并不是事先知道的。在发布的开发周期中,它们可能会发生变化,直到最终的功能被集成为止。因此发布的版本号也是未知的。
使用JEP 223的版本号语义,每个在JDK发布版上工作或者在其上构建或使用组件的人都必须先说明发布的发布日期,然后切换到说版本号,已知。维护库,框架和工具的开发人员必须准备好更改在每个JDK发布周期后期检查版本号的代码。这对所有参与者来说都很尴尬和混乱。
因此,这里提出的主要改变是重新编制版本号来编码,而不是编码的兼容性和重要性,而是按照发布周期的时间推移。这是更适合基于时间的发布模型,因为每个发布周期,因此每个发布的版本号,总是提前知道。
后续的版本格式为:[1-9][0-9]*((\.0)*\.[1-9][0-9]*)*
该格式可以是任意长度,但前四个被赋予特定含义,如:$FEATURE.$INTERIM.$UPDATE.$PATCH
- $FEATURE:功能发布计数器,不管发布内容如何,都会为每个功能发布增加。功能可能会添加到功能发布中; 如果提前通知提前至少发布一次功能发布,它们也可能会被删除。如果合理,可能会做出不兼容的更改。
- $INTERIM:临时版本计数器,对于包含兼容错误修复和增强功能的非功能版本递增,但没有不兼容的更改,没有功能移除,也没有对标准API的更改。
- $UPDATE:更新版本计数器增加了兼容更新版本,可解决新功能中的安全问题,回归和错误。
- $PATCH:紧急修补程序释放计数器只有在需要生成紧急释放以解决关键问题时才会增加。
-
版本号永远不会有零元素结尾。如果一个元素及其后的所有元素在逻辑上具有零值,那么它们全部被省略。
在严格六个月的发布模式下,版本号如下所示:
- $FEATURE 每六个月增加一次。如:2018年3月发布的是JDK 10,2018年9月发布的是JDK 11,等等。
- $INTERIM 总是为零,因为六个月的模型不包括临时版本。在此为保留其灵活性,以便将来对版本模型的修订可能包括此类版本。
$UPDATE 在$FEATURE发布后的一个月递增,之后每三个月递增一次:如2018年4月发布JDK 10.0.1。7月发布的是JDK 10.0.2等等。
-
备用内存设备上分配堆内存
启用HotSpot VM以在用户指定的备用内存设备上分配Java对象堆。随着廉价的NV-DIMM内存的可用性,未来的系统可能配备了异构的内存架构。这种技术的一个例子是英特尔的3D XPoint。这样的体系结构,除了DRAM之外,还会有一种或多种类型的非DRAM内存,具有不同的特征。具有与DRAM具有相同语义的可选内存设备,包括原子操作的语义,因此可以在不改变现有应用程序代码的情况下使用DRAM代替DRAM。所有其他的内存结构,如代码堆、metaspace、线程堆栈等等,都将继续驻留在DRAM中。
参考以下使用案例: