互联网技术的更新日新月异,而对于jdk,大部分人平时都是使用的jdk1.8,然而,如今jdk已经更新到了15马上变16,本篇文章我们就来看看jdk9到底更新了一些什么内容。

目录结构变化

有关jdk9的下载安装与环境配置在这里就不作介绍了,直接来看看它与jdk8的第一个区别,目录结构的变化。

上图是jdk8的目录结构,下图是jdk9的目录结构:

两者最明显的区别在于jdk9中已经不包含jre了,其它内容变化倒是不大。

模块化

我们知道,Java编写的项目是比较臃肿的,编译运行需要耗费大量的时间,为此,java9提供了模块化,使得开发者可以指定项目具体需要使用哪些类库,以排除无关紧要的jar包,增加项目运行效率。

首先创建一个Java项目:

在该项目下创建两个模块,创建方法为 右击项目-->New-->Module:

模块创建完成后,在module-1中编写一个Bean:

package com.wwj.bean;public class Person { private String name; private int age; public Person() { } public Person(String name, int age) { this.name = name; this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Override public String toString() { return "Person{" + "name='" + name + '\'' + ", age=" + age + '}'; }}

然后我们在module-2中创建一个测试文件:

会发现在module-2中是无法使用module-1中的Person类的,这是因为jdk9对项目进行了模块化,若想要使用到其它模块的类,需要作如下操作。

在module-1中创建module-info文件:

编写如下内容:

module module1 { // 导出包 exports com.wwj.bean;}

并在module-2中创建module-info文件,编写如下内容:

module module2 { // 引入模块 requires module1;}

这样我们就可以顺利地使用到module-1中com.wwj.bean包下的类了:

再举个例子,比如你想打印日志,你就需要使用Logger类,然而:

此时Logger类也是报错的,而且你会发现导包是导入不了的,此时我们就需要在module-info中引入Logger模块:

module module2 { requires module1; requires java.logging;}

这样就能够使用Logger类了:

通过这样的方式,使得虚拟机在加载项目时只会去加载module-info中配置的模块,从而大大提升了运行效率。

jshell命令

在jdk9之前,我们若是想执行一个非常简单的程序,比如做一个加法,你需要创建java文件,然后编译执行。

这显然非常繁琐,那它能不能够像Python那样有一个交互式的编程环境呢?为此,jdk9提供了jshell。

使用方法非常简单,在cmd窗口中输入jshell:

在jshell中,我们能够进行输出、定义变量、计算等等很多操作,jshell也会在我们按下回车后立即给予我们反馈:

创建方法并调用:

jshell还提供了一些非常好用的命令,比如:/list,通过它能够查看历史执行的命令:

jshell> /list 1 : System.out.println("Hello World 3 : System.out.println("Hello World 4 : int i = 10; 5 : int j = 10; 6 : int result = i + j; 7 : System.out.println(result); 8 : public int add(int i,int j){ return i + j; } 9 : System.out.println(add(i,j));

/imports,查看导入的包:

jshell> /imports| import java.io.*| import java.math.*| import java.net.*| import java.nio.file.*| import java.util.*| import java.util.concurrent.*| import java.util.function.*| import java.util.prefs.*| import java.util.regex.*| import java.util.stream.*

/vars,查看定义的变量:

jshell> /vars| int i = 10| int j = 10| int result = 20

/methods,查看定义的方法:

jshell> /methods| int add(int,int)

/edit,弹出对话框用于修改代码:

前言多版本兼容Jar包

当一个新版本的jdk出现时,开发者并不愿意立马将其开发环境切换到新的版本,因为它的很多项目还是用之前的jdk进行开发的,当切换了新版本的jdk后,很可能会因为其不兼容一些老的jar包从而导致项目出错。

jdk9考虑到了这一点,其多版本兼容jar包的功能可以使开发者创建仅在特定版本的java环境中运行库程序选择使用的版本。

现在有这样一个项目,其中有两个包,一个java包,一个java-9包。

java包中有两个类,分别是:

public class Generator { public Set createStrings() { Set strings = new HashSet(); strings.add("Java"); strings.add("8"); return strings; }} public class Application { public static void testMultiJar(){ Generator gen = new Generator(); System.out.println("Generated strings: " + gen.createStrings()); }}

而java-9中的类为:

public class Generator { public Set createStrings() { return Set.of("Java", "9"); }}

现在我们将对这个项目进行打包,得到一个.jar文件——multijar.jar。

下面就来测试一下,新建一个Java8的项目,并编写测试代码:

public class MultiJar { public static void main(String[] args) { Application.testMultiJar(); }}

记得将刚才的jar包导入到项目中,运行结果为:

Generated strings: [Java, 8]

我们再将这段代码放到Java9环境的项目中运行一下,得到结果:

Generated strings: [9, Java]

可以看到,同一段代码在不同环境下会有对应的不同表示,这就是多版本兼容的jar包。

接口可以定义私有方法了

从jdk9开始,接口可以定义私有方法了,具体的话也没有什么好说的,直接看代码:

public interface InterfaceTest { //jdk7中只能声明全局常量(使用public static final修饰)和抽象方法(使用public abstract修饰) int num = 10; void add(int i,int j); //jdk8中还能够声明静态方法和默认方法 static void staticMethod(){ } default void defaultMethod(){ } //jdk9中能够定义私有方法 private void privateMethod(){ }}

集合中的泛型

在jdk8以前,我们若想定义一个带有泛型的集合,必须这样编写:

Set set = new HashSet();

而在jdk8中,我们可以省略后面的泛型,因为它可以进行类型的自动推断:

Set set = new HashSet<>();

在jdk9中,我们还能够对集合进行如下编写:

Set set = new HashSet<>(){};

这行代码的意思是创建一个继承于HashSet的匿名子类对象,它将与Set共同使用泛型,那么这样有什么好处呢?

好处在于当你需要改造Set中的某个方法时,能够很方便地实现,比如:

public static void main(String[] args) { Set set = new HashSet<>(){ @Override public boolean add(String s) { return super.add(s + "--"); } }; set.add("zhangsan"); set.add("lisi"); set.add("wangwu"); for (String str : set) { System.out.println(str); }}

运行结果:

wangwu--zhangsan--lisi--

异常处理

对于IO流的异常处理一直为人所诟病,传统的异常处理过程如下:

FileInputStream in = null;try { in = new FileInputStream("");} catch (FileNotFoundException e) { e.printStackTrace();}finally { if(in != null){ try { in.close(); } catch (IOException e) { e.printStackTrace(); } }}

可以看到代码非常的臃肿,在jdk8中,我们还有另外一套解决方案:

try (FileInputStream in = new FileInputStream("")) { in.close();} catch (IOException e) { e.printStackTrace();}

将资源放在try语句的括号内,我们就不需要手动去关闭流资源了。

而在jdk9中,我们可以在try()中调用已经实例化的资源对象:

InputStreamReader reader = new InputStreamReader(System.in);try (reader) { reader.read();} catch (IOException e) { e.printStackTrace();}

这种方式在jdk9之前是不支持的。

下划线的使用限制

在jdk8中,下划线是可以单独作为变量名进行定义的:

int _ = 100;

而jdk9中禁止了这种变量的定义:

前言String存储结构的变化

在jdk8中,字符串的底层采用的是char数组:

而在jdk9中,它不再使用char数组实现,取而代之的是byte数组:

因为在UTF-16编码中,一个字符会占用两个字节,而大部分情况下,开发者使用的String中包含了较多的字母和数字,它们均只用一个字节就能够存储,所以采用char数组存储字符串会造成大量资源的浪费,为此,jdk9中特别设计了String的实现,将其底层改为了byte数组。

只读集合

jdk8中提供了unmodifiableList()方法来将一个集合转变为只读集合:

public static void main(String[] args) { List list = new ArrayList<>(); list.add("a"); list.add("b"); list.add("c"); List readList = Collections.unmodifiableList(list); // 只读集合不允许添加元素 // readList.add("d"); readList.forEach(System.out::println);}

若是想创建只读的Set集合,只需修改方法名即可:

public static void main(String[] args) { Set set = Collections.unmodifiableSet(new HashSet<>(Arrays.asList(1, 2, 3, 4, 5))); set.forEach(System.out::println);}

只读的map集合也是如此:

public static void main(String[] args) { Map map = Collections.unmodifiableMap(new HashMap<>() { { put("zhangsan", 20); put("lisi", 21); put("wangwu", 22); } }); map.forEach((k,v) -> System.out.println(k + ":" + v));}

注意这里使用到了jdk9中的另一新特性来初始化Map集合,这在集合中的泛型已经介绍过了。

以上均是jdk8中创建只读集合的方式,在jdk9中,它的创建方式只会更加简单:

public static void main(String[] args) { List list = List.of(1, 2, 3, 4, 5); list.forEach(System.out::println);}

通过of()方法创建的集合它就是一个只读集合,是不可以再对其进行修改的。

然后是Set集合和Map集合:

public static void main(String[] args) { //创建只读Set Set set = Set.of(1, 2, 3, 4); //创建只读Map Map map = Map.of("zhangsan", 20, "lisi", 21, "wangwu", 22); //创建只读Map的第二种方式 Map map = Map.ofEntries(Map.entry("zhangsan", 20), Map.entry("lisi", 21));}

Stream的增强

首先是takeWhile方法:

public static void main(String[] args) { // takeWhile List list = Arrays.asList(1,3,2,5,4); Stream stream = list.stream(); Stream newStream = stream.takeWhile(x -> x < 3); newStream.forEach(System.out::println);}

在该场景中,takeWhile方法的作用是从集合第一个元素开始查找小于3的元素,第一个元素1小于3;第二个元素3不小于3,此时后面的所有元素都会被舍弃,所以运行结果为:

1

其次是dropWhile方法:

public static void main(String[] args) { // dropWhile List list = Arrays.asList(1,3,2,5,4); Stream stream = list.stream(); Stream newStream = stream.dropWhile(x -> x < 3); newStream.forEach(System.out::println);}

在该场景中,dropWhile方法的作用是从集合第一个元素开始查找小于3的元素,第一个元素1小于3,会被舍弃;第二个元素3不小于3,此时后面的所有元素都被保留,所以运行结果为:

3254

最后是ofNullable方法,它允许Stream中存放单个null值:

public static void main(String[] args) { //ofNullable Stream

java age_这些Java9 超牛的新特性,你竟然还没用过?相关推荐

  1. Java 每半年就会更新一次新特性,再不掌握就要落伍了:Java9 的新特性

    你好,我是看山. 本文收录在 <从小工到专家的 Java 进阶之旅> 系列专栏中. 从 2017 年开始,Java 版本更新策略从原来的每两年一个新版本,改为每六个月一个新版本,以快速验证 ...

  2. 尚硅谷Java入门视频教程第十七章——Java9Java10Java11新特性

    尚硅谷Java入门视频教程第十七章--Java9&Java10&Java11新特性 第17章:Java9&Java10&Java11新特性 17.1 Java 9 的新 ...

  3. Java 每半年就会更新一次新特性,再不掌握就要落伍了:Java11 的新特性

    文章目录 概述 增强 String repeat strip.stripLeading.stripTrailing isBlank lines 增强文件读写 增强集合的数组操作 增强函数 Predic ...

  4. Java 每半年就会更新一次新特性,再不掌握就要落伍了:Java12 的新特性

    本文收录在 <从小工到专家的 Java 进阶之旅> 系列专栏中. 你好,我是看山. 从 2017 年开始,Java 版本更新策略从原来的每两年一个新版本,改为每六个月一个新版本,以快速验证 ...

  5. Java 每半年就会更新一次新特性,再不掌握就要落伍了:Java10 的新特性

    你好,我是看山. 本文收录在 <从小工到专家的 Java 进阶之旅> 系列专栏中. 从 2017 年开始,Java 版本更新策略从原来的每两年一个新版本,改为每六个月一个新版本,以快速验证 ...

  6. Java 每半年就会更新一次新特性,再不掌握就要落伍了:Java13 的新特性

    你好,我是看山. 本文收录在 <从小工到专家的 Java 进阶之旅> 系列专栏中. 从 2017 年开始,Java 版本更新策略从原来的每两年一个新版本,改为每六个月一个新版本,以快速验证 ...

  7. 如约而至,Java 10 正式发布:包含 109 项新特性

    如约而至,Java 10 正式发布:包含 109 项新特性 期待已久,没有跳票的 Java 10 已正式发布!你可以通过这里下载 Java 10 正式版. 此前我们曾报道过,为了更快地迭代,以及跟进社 ...

  8. Java复习第11天---11.4---Java8新特性---Stream流常用方法3和综合案例

    Java复习第11天---11.4---Java8新特性---Stream流常用方法3和综合案例 目录 文章目录 1.count:计数-终结方法 2.limit:取前几个元素-延迟方法 3.skip: ...

  9. Java复习第11天---11.3---Java8新特性---Stream流特点和常用方法2

    Java复习第11天---11.3---Java8新特性---Stream流特点和常用方法2 目录 文章目录 1.Stream流特点 2.filter:过滤 3.map:映射 ***后记*** : 内 ...

  10. Java复习第11天---11.2---Java8新特性---Stream流获取方式和常用方法1

    Java复习第11天---11.2---Java8新特性---Stream流获取方式和常用方法1 目录 文章目录 1.Stream流的2中获取方式 1.1.集合的stream方法 1.2.Stream ...

最新文章

  1. java第二天_进制转换原理和补码存储方式作业
  2. 成功解决极其刁钻bug之TypeError: ‘<=‘ not supported between instances of ‘list‘ and ‘int‘
  3. CSAPP第4章家庭作业参考答案
  4. matlab的支持向量机调参,支持向量机(2)-应用
  5. python中有很多包管理工具、以下哪种不是_python试卷_共4页
  6. SCCM 2012系列16 操作系统播发⑤
  7. 【HDU - 4417】Super Mario(查询区间小于K的数的个数,主席树)
  8. this和arguments
  9. s3c6410 jpeg编码 linux,S3C6410 裸机硬件JPEG解码
  10. 大型综合体弱电智能化解决方案标书
  11. bat脚本保存dir结果_Tomcat的启停脚本源码解析
  12. 2010年安全主题展望
  13. Class的三种构造方法
  14. 【Unity步步升】导航网格、寻路算法及AI行为树等应用与实践...
  15. python双向链表以及双向循环链表
  16. 人工智能辅助服装设计 | Mixlab论文带读
  17. 智比奈特万兆光口网卡 ZB-10G-1F 驱动安装和带宽测试
  18. bas64图片加密解密
  19. 二级C语言上机考试评分标准,浅谈二级C语言上机考试评分原理
  20. Latex 定义definition

热门文章

  1. week03_python标准库datetime
  2. Tomcat Server
  3. Citrix入门教程,之windows server2008 r2安装
  4. 远程管理技术对服务器管理的影响
  5. 第七章 数据库设计(联系毕业论文))
  6. 电脑计算机无法安3.5,win10 net framework 3.5安装不了的完美解决办法
  7. Oracle 查看表空间使用率,表空间扩展
  8. python中基础知识_Python中的一些基础知识
  9. linux添加磁盘分区,linux添加磁盘分区
  10. 点击控件动态创建新页面