JDK各个版本的新特性

JDK各个版本的新特性的对比

jdk1.5的新特性:
1. 泛型
  ArrayList list=new ArrayList()------>ArrayList<Integer>list=new ArrayList<Integer>();
2 自动装箱/拆箱
  int i=list.get(0).parseInt();-------->int i=list.get(0);原始类型与对应的包装类不用显式转换
3 for-each
   i=0;i<a.length;i++------------>for(int i:a){......}
4 static import
  Math.sqrt();--------------->sqrt();
5 变长参数
  int sum(int ...intlist)有任意个参数,把他看作数组


jdk1.6的新特性
1.增强的for循环语句

1 Integer[] numbers = computeNumbers();
2 for (int i=0; i < numbers.length ; i++)
3 sum += numbers[i];
4 ||
5 int sum = 0;
6 for ( int number: computeNumbers() )
7 sum += number;

2.监视和管理
  Java SE 6中对内存泄漏增强了分析以及诊断能力。当遇到java.lang.OutOfMemory异常的时候,可以得到一个完整的堆栈信息,
  并且当堆已经满了的时候,会产生一个Log文件来记录这个致命错误。另外,JVM还添加了一个选项,允许你在堆满的时候运行脚本。
3.插入式注解处理
  插入式注解处理API(JSR 269)提供一套标准API来处理Annotations
4.安全性


jdk1.7的新特性
1.模块化特性
  Java7也是采用了模块的划分方式来提速,一些不是必须的模块并没有下载和安装,当虚拟机需要的时候,再下载相应的模块,
  同时对启动速度也有了很大的改善。

2.多语言支持
  Java7的虚拟机对多种动态程序语言增加了支持,比如:Rubby、 Python等等。

3.开发者的开发效率得到了改善
  switch中可以使用字符串
  在多线程并发与控制方面:轻量级的分离与合并框架,一个支持并发访问的HashMap等等。
  通过注解增强程序的静态检查。
  提供了一些新的API用于文件系统的访问、异步的输入输出操作、Socket通道的配置与绑定、多点数据包的传送等等。

4.执行效率的提高
  对对象指针由64位压缩到与32位指针相匹配的技术使得内存和内存带块的消耗得到了很大的降低因而提高了执行效率。
  提供了新的垃圾回收机制(G1)来降低垃圾回收的负载和增强垃圾回收的效果。
 

JDK1.8的新特性
一、接口的默认方法
  Java 8允许我们给接口添加一个非抽象的方法实现,只需要使用 default关键字即可,这个特征又叫做扩展方法。

1 interface interface2{
2     int doubleInt(int x);
3     // 接口的默认方法
4     default int add(int x,int y){
5         return x+y;
6     }
7 }


二、Lambda 表达式
  在Java 8 中你就没必要使用这种传统的匿名对象的方式了,Java 8提供了更简洁的语法,lambda表达式:

Collections.sort(names, (String a, String b) -> {

    return b.compareTo(a);

});

三、函数式接口
  Lambda表达式是如何在java的类型系统中表示的呢?每一个lambda表达式都对应一个类型,通常是接口类型。而“函数式接口”是指仅仅只包含一个抽象方法的接口,每一个该类型的lambda表达式都会被匹配到这个抽象方法。因为 默认方法 不算抽象方法,所以你也可以给你的函数式接口添加默认方法。 

 1 class MyMoney {
 2     private final int money;
 3 
 4     public MyMoney(int money) {
 5         this.money = money;
 6     }
 7 
 8     public void printMoney(Function<Integer, String> moneyFormat) {
 9         System.out.println("我的存款:" + moneyFormat.apply(this.money));
10     }
11 }
12 
13 public class MoneyDemo {
14 
15     public static void main(String[] args) {
16         MyMoney me = new MyMoney(99999999);
17 
18         Function<Integer, String> moneyFormat = i -> new DecimalFormat("#,###")
19                 .format(i);
20         
21         // 函数接口链式操作
22         me.printMoney(moneyFormat.andThen(s -> "人民币 " + s));
23     }
24 
25 }

四、方法与构造函数引用
  Java 8 允许你使用 :: 关键字来传递方法或者构造函数引用,上面的代码展示了如何引用一个静态方法,我们也可以引用一个对象的方法:

 1 class Dog {
 2     private String name = "哮天犬";
 3 
 4     /**
 5      * 默认10斤狗粮
 6      */
 7     private int food = 10;
 8 
 9     public Dog() {
10 
11     }
12 
13     /**
14      * 带参数的构造函数
15      * 
16      * @param name
17      */
18     public Dog(String name) {
19         this.name = name;
20     }
21 
22     /**
23      * 狗叫,静态方法
24      * 
25      * @param dog
26      */
27     public static void bark(Dog dog) {
28         System.out.println(dog + "叫了");
29     }
30 
31     /**
32      * 吃狗粮 JDK
33      * 
34      * 默认会把当前实例传入到非静态方法,参数名为this,位置是第一个;
35      * 
36      * @param num
37      * @return 还剩下多少斤
38      */
39     public int eat(int num) {
40         System.out.println("吃了" + num + "斤狗粮");
41         this.food -= num;
42         return this.food;
43     }
44 
45     @Override
46     public String toString() {
47         return this.name;
48     }
49 }
50 
51 public class MethodRefrenceDemo {
52 
53     public static void main(String[] args) {
54         Dog dog = new Dog();
55         dog.eat(3);
56 
57         // 方法引用
58         Consumer<String> consumer = System.out::println;
59         consumer.accept("接受的数据");
60 
61         // 静态方法的方法引用
62         Consumer<Dog> consumer2 = Dog::bark;
63         consumer2.accept(dog);
64 
65         // 非静态方法,使用对象实例的方法引用
66         // Function<Integer, Integer> function = dog::eat;
67         // UnaryOperator<Integer> function = dog::eat;
68         IntUnaryOperator function = dog::eat;
69         
70         // dog置空,不影响下面的函数执行,因为java 参数是传值
71         dog = null;
72         System.out.println("还剩下" + function.applyAsInt(2) + "斤");
73         //
74         // // 使用类名来方法引用
75         // BiFunction<Dog, Integer, Integer> eatFunction = Dog::eat;
76         // System.out.println("还剩下" + eatFunction.apply(dog, 2) + "斤");
77         //
78         // // 构造函数的方法引用
79         // Supplier<Dog> supplier = Dog::new;
80         // System.out.println("创建了新对象:" + supplier.get());
81         //
82         // // 带参数的构造函数的方法引用
83         // Function<String, Dog> function2 = Dog::new;
84         // System.out.println("创建了新对象:" + function2.apply("旺财"));
85 
86         // 测试java变量是传值还是穿引用
87         List<String> list = new ArrayList<>();
88         test(list);
89 
90         System.err.println(list);
91     }
92 
93     private static void test(List<String> list) {
94         list = null;
95     }
96 }
View Code

五、Lambda 作用域
  在lambda表达式中访问外层作用域和老版本的匿名对象中的方式很相似。你可以直接访问标记了final的外层局部变量,或者实例的字段以及静态变量。

六、访问局部变量
  可以直接在lambda表达式中访问外层的局部变量:

七、访问对象字段与静态变量 
  和本地变量不同的是,lambda内部对于实例的字段以及静态变量是即可读又可写。该行为和匿名对象是一致的:

八、访问接口的默认方法
  JDK 1.8 API包含了很多内建的函数式接口,在老Java中常用到的比如Comparator或者Runnable接口,这些接口都增加了@FunctionalInterface注解以便能用在lambda上。
  Java 8 API同样还提供了很多全新的函数式接口来让工作更加方便,有一些接口是来自Google Guava库里的,即便你对这些很熟悉了,还是有必要看看这些是如何扩展到lambda上使用的。

JDK1.9的新特性:

1. Java 平台级模块系统

  Java 9 的定义功能是一套全新的模块系统。当代码库越来越大,创建复杂,盘根错节的“意大利面条式代码”的几率呈指数级的增长。这时候就得面对两个基础的问题: 很难真正地对代码进行封装, 而系统并没有对不同部分(也就是 JAR 文件)之间的依赖关系有个明确的概念。每一个公共类都可以被类路径之下任何其它的公共类所访问到, 这样就会导致无意中使用了并不想被公开访问的 API。此外,类路径本身也存在问题: 你怎么知晓所有需要的 JAR 都已经有了, 或者是不是会有重复的项呢? 模块系统把这俩个问题都给解决了。

模块化的 JAR 文件都包含一个额外的模块描述器。在这个模块描述器中, 对其它模块的依赖是通过 “requires” 来表示的。另外, “exports” 语句控制着哪些包是可以被其它模块访问到的。所有不被导出的包默认都封装在模块的里面。如下是一个模块描述器的示例,存在于 “module-info.java” 文件中:

我们可以如下展示模块:

module blog {
  exports com.pluralsight.blog;
 
  requires cms;
}

  请注意,两个模块都包含封装的包,因为它们没有被导出(使用橙色盾牌可视化)。 没有人会偶然地使用来自这些包中的类。Java 平台本身也使用自己的模块系统进行了模块化。通过封装 JDK 的内部类,平台更安全,持续改进也更容易。

当启动一个模块化应用时, JVM 会验证是否所有的模块都能使用,这基于 `requires` 语句——比脆弱的类路径迈进了一大步。模块允许你更好地强制结构化封装你的应用并明确依赖。你可以在这个课程中学习更多关于 Java 9 中模块工作的信息 。

2. Linking

  当你使用具有显式依赖关系的模块和模块化的 JDK 时,新的可能性出现了。你的应用程序模块现在将声明其对其他应用程序模块的依赖以及对其所使用的 JDK 模块的依赖。为什么不使用这些信息创建一个最小的运行时环境,其中只包含运行应用程序所需的那些模块呢? 这可以通过 Java 9 中的新的 jlink 工具实现。你可以创建针对应用程序进行优化的最小运行时映像而不需要使用完全加载 JDK 安装版本。

3. JShell : 交互式 Java REPL

  许多语言已经具有交互式编程环境,Java 现在加入了这个俱乐部。您可以从控制台启动 jshell ,并直接启动输入和执行 Java 代码。 jshell 的即时反馈使它成为探索 API 和尝试语言特性的好工具。

  测试一个 Java 正则表达式是一个很好的说明 jshell 如何使您的生活更轻松的例子。 交互式 shell 还可以提供良好的教学环境以及提高生产力,您可以在此了解更多信息。在教人们如何编写 Java 的过程中,不再需要解释 “public static void main(String [] args)” 这句废话。

4. 改进的 Javadoc

  有时一些小事情可以带来很大的不同。你是否就像我一样在一直使用 Google 来查找正确的 Javadoc 页面呢? 这不再需要了。Javadoc 现在支持在 API 文档中的进行搜索。另外,Javadoc 的输出现在符合兼容 HTML5 标准。此外,你会注意到,每个 Javadoc 页面都包含有关 JDK 模块类或接口来源的信息。

5. 集合工厂方法

  通常,您希望在代码中创建一个集合(例如,List 或 Set ),并直接用一些元素填充它。 实例化集合,几个 “add” 调用,使得代码重复。 Java 9,添加了几种集合工厂方法:

Set<Integer> ints = Set.of(1, 2, 3);
List<String> strings = List.of("first", "second");

  除了更短和更好阅读之外,这些方法也可以避免您选择特定的集合实现。 事实上,从工厂方法返回已放入数个元素的集合实现是高度优化的。这是可能的,因为它们是不可变的:在创建后,继续添加元素到这些集合会导致 “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 8 为我们带来了接口的默认方法。 接口现在也可以包含行为,而不仅仅是方法签名。 但是,如果在接口上有几个默认方法,代码几乎相同,会发生什么情况? 通常,您将重构这些方法,调用一个可复用的私有方法。 但默认方法不能是私有的。 将复用代码创建为一个默认方法不是一个解决方案,因为该辅助方法会成为公共API的一部分。 使用 Java 9,您可以向接口添加私有辅助方法来解决此问题:

public interface MyInterface {
 
    void normalInterfaceMethod();
 
    default void interfaceMethodWithDefault() {  init(); }
 
    default void anotherDefaultMethod() { init(); }
 
    // This method is not part of the public API exposed by MyInterface
    private void 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());

  除了这个简单的请求/响应模型之外,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

  在上述场景中, multirelease.jar 可以在 Java 9 中使用, 不过 Helper 这个类使用的不是顶层的 multirelease.Helper 这个 class, 而是处在“META-INF/versions/9”下面的这个。这是特别为 Java 9 准备的 class 版本,可以运用 Java 9 所提供的特性和库。同时,在早期的 Java 诸版本中使用这个 JAR 也是能运行的,因为较老版本的 Java 只会看到顶层的这个 Helper 类。

如你所见,Java 9 提供了一大堆或大或小的功能特性,你准备好了么?


</div>
  </div>

  

 
原文地址:https://www.cnblogs.com/a-fei/p/12112659.html