赶快看看Java11,否则你就out了!
这个是我的博客原文的连接。Java更新的太快了,都学不过来了,最近了解一些Java8之后的一些特性,写下来但愿对你们有帮助。java
因为直接从Java8跨越到Java11,因此特性介绍就把Java9-Java11的部分特性一块儿介绍一下。想要了解Java8特性的朋友能够去个人博客找「Java8系列」。git
Jshell在Java9中就被提出来了,能够直接在终端写Java程序,回车就能够执行。Jshell默认会导入下面的一些包,因此在Jshell环境中这些包的内容都是可使用的。github
import java.lang.*; 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.*;
Jshell是在 Java 9 中引入的。它提供了一个交互式 shell,用于快速原型、调试、学习 Java 及 Java API,全部这些都不须要 public static void main 方法,也不须要在执行以前编译代码。sql
打开终端,键入jshell进入jshell环境,而后输入/help intro能够查看Jshell的介绍。docker
lixiaoshuang@localhost ~ jshell | 欢迎使用 JShell -- 版本 11.0.2 | 要大体了解该版本, 请键入: /help intro jshell> /help intro | | intro | ===== | | 使用 jshell 工具能够执行 Java 代码,从而当即获取结果。 | 您能够输入 Java 定义(变量、方法、类等等),例如:int x = 8 | 或 Java 表达式,例如:x + x | 或 Java 语句或导入。 | 这些小块的 Java 代码称为“片断”。 | | 这些 jshell 工具命令还可让您了解和 | 控制您正在执行的操做,例如:/list | | 有关命令的列表,请执行:/help jshell>
Jshell确实是一个好用的小工具,这里不作过多介绍,我就举一个例子,剩下的你们本身体会。好比咱们如今就想随机生成一个UUID,之前须要这么作:shell
如今只须要,进入打开终端键入jshell,而后直接输入var uuid = UUID.randomUUID()
回车。就能够看到uuid的回显,这样咱们就获得了一个uuid。并不须要public static void main(String[] args);segmentfault
lixiaoshuang@localhost ~ jshell | 欢迎使用 JShell -- 版本 11.0.2 | 要大体了解该版本, 请键入: /help intro jshell> var uuid = UUID.randomUUID(); uuid ==> 9dac239e-c572-494f-b06d-84576212e012 jshell>
在Jshell环境中键入/exit
就能够退出。api
lixiaoshuang@localhost ~ lixiaoshuang@localhost ~ jshell | 欢迎使用 JShell -- 版本 11.0.2 | 要大体了解该版本, 请键入: /help intro jshell> var uuid = UUID.randomUUID(); uuid ==> 9dac239e-c572-494f-b06d-84576212e012 jshell> /exit | 再见 lixiaoshuang@localhost ~
模块化就是增长了更高级别的聚合,是Package的封装体。Package是一些类路径名字的约定,而模块是一个或多个Package组成的封装体。安全
java9之前 :package => class/interface。oracle
java9之后 :module => package => class/interface。
那么JDK被拆为了哪些模块呢?打开终端执行java --list-modules
查看。
lixiaoshuang@localhost ~ java --list-modules java.base@11.0.2 java.compiler@11.0.2 java.datatransfer@11.0.2 java.desktop@11.0.2 java.instrument@11.0.2 java.logging@11.0.2 java.management@11.0.2 java.management.rmi@11.0.2 java.naming@11.0.2 java.net.http@11.0.2 java.prefs@11.0.2 java.rmi@11.0.2 java.scripting@11.0.2 java.se@11.0.2 java.security.jgss@11.0.2 java.security.sasl@11.0.2 java.smartcardio@11.0.2 java.sql@11.0.2 java.sql.rowset@11.0.2 java.transaction.xa@11.0.2 java.xml@11.0.2 java.xml.crypto@11.0.2 jdk.accessibility@11.0.2 jdk.aot@11.0.2 jdk.attach@11.0.2 jdk.charsets@11.0.2 jdk.compiler@11.0.2 jdk.crypto.cryptoki@11.0.2 jdk.crypto.ec@11.0.2 jdk.dynalink@11.0.2 jdk.editpad@11.0.2 jdk.hotspot.agent@11.0.2 jdk.httpserver@11.0.2 jdk.internal.ed@11.0.2 jdk.internal.jvmstat@11.0.2 jdk.internal.le@11.0.2 jdk.internal.opt@11.0.2 jdk.internal.vm.ci@11.0.2 jdk.internal.vm.compiler@11.0.2 jdk.internal.vm.compiler.management@11.0.2 jdk.jartool@11.0.2 jdk.javadoc@11.0.2 jdk.jcmd@11.0.2 jdk.jconsole@11.0.2 jdk.jdeps@11.0.2 jdk.jdi@11.0.2 jdk.jdwp.agent@11.0.2 jdk.jfr@11.0.2 jdk.jlink@11.0.2 jdk.jshell@11.0.2 jdk.jsobject@11.0.2 jdk.jstatd@11.0.2 jdk.localedata@11.0.2 jdk.management@11.0.2 jdk.management.agent@11.0.2 jdk.management.jfr@11.0.2 jdk.naming.dns@11.0.2 jdk.naming.rmi@11.0.2 jdk.net@11.0.2 jdk.pack@11.0.2 jdk.rmic@11.0.2 jdk.scripting.nashorn@11.0.2 jdk.scripting.nashorn.shell@11.0.2 jdk.sctp@11.0.2 jdk.security.auth@11.0.2 jdk.security.jgss@11.0.2 jdk.unsupported@11.0.2 jdk.unsupported.desktop@11.0.2 jdk.xml.dom@11.0.2 jdk.zipfs@11.0.2
你们都知道JRE中有一个超级大的rt.jar(60多M),tools.jar也有几十兆,之前运行一个hello world也须要上百兆的环境。
模块的是经过module-info.java进行定义,编译后打包后,就成为一个模块的实体。下面来看下最简单的模块定义。
open
用来指定开放模块,开放模块的全部包都是公开的,public的能够直接引用使用,其余类型能够经过反射获得。
open module module.one { //导入日志包 requires java.logging; }
opens
opens 用来指定开放的包,其中public类型是能够直接访问的,其余类型能够经过反射获得。
module module.one { opens <package>; }
exports
exports用于指定模块下的哪些包能够被其余模块访问。
module module.one { exports <package>; exports <package> to <module1>, <module2>...; }
requires
该关键字声明当前模块与另外一个模块的依赖关系。
module module.one { requires <package>; }
uses、provides…with…
uses语句使用服务接口的名字,当前模块就会发现它,使用java.util.ServiceLoader类进行加载,必须是本模块中的,不能是其余模块中的.其实现类能够由其余模块提供。
module module.one { //对外提供的接口服务 ,下面指定的接口以及提供服务的impl,若是有多个实现类,用用逗号隔开 uses <接口名>; provides <接口名> with <接口实现类>,<接口实现类>; }
var是Java10中新增的局部类型变量推断。它会根据后面的值来推断变量的类型,因此var必需要初始化。
例:
var a; ❌ var a = 1; ✅
var定义局部变量
var a = 1; 等于 int a = 1;
var接收方法返回时
var result = this.getResult(); 等于 String result = this.getResult();
var循环中定义局部变量
for (var i = 0; i < 5; i++) { System.out.println(i); } 等于 for (int i = 0; i < 5; i++) { System.out.println(i); }
var结合泛型
var list1 = new ArrayList<String>(); //在<>中指定了list类型为String 等于 List<String> list1 = new ArrayList<>(); var list2 = new ArrayList<>(); //<>里默认会是Object
var在Lambda中使用(java11才可使用)
Consumer<String> Consumer = (var i) -> System.out.println(i); 等于 Consumer<String> Consumer = (String i) -> System.out.println(i);
// 判断字符串是否为空白 " ".isBlank(); // true // 去除首尾空格 " Hello Java11 ".strip(); // "Hello Java11" // 去除尾部空格 " Hello Java11 ".stripTrailing(); // " Hello Java11" // 去除首部空格 " Hello Java11 ".stripLeading(); // "Hello Java11 " // 复制字符串 "Java11".repeat(3); // "Java11Java11Java11" // 行数统计 "A\nB\nC".lines().count(); // 3
从Java 9 开始,jdk里面就为集合(List、Set、Map)增长了of和copyOf方法。它们用来建立不可变集合。
示例一:
var list = List.of("Java", "Python", "C"); //不可变集合 var copy = List.copyOf(list); //copyOf判断是不是不可变集合类型,若是是直接返回 System.out.println(list == copy); // true var list = new ArrayList<String>(); // 这里返回正常的集合 var copy = List.copyOf(list); // 这里返回一个不可变集合 System.out.println(list == copy); // false
示例二:
var set = Set.of("Java", "Python", "C"); var copy = Set.copyOf(set); System.out.println(set == copy); // true var set1 = new HashSet<String>(); var copy1 = List.copyOf(set1); System.out.println(set1 == copy1); // false
示例三:
var map = Map.of("Java", 1, "Python", 2, "C", 3); var copy = Map.copyOf(map); System.out.println(map == copy); // true var map1 = new HashMap<String, Integer>(); var copy1 = Map.copyOf(map1); System.out.println(map1 == copy1); // false
注意:使用 of 和 copyOf 建立的集合为不可变集合,不能进行添加、删除、替换、排序等操做,否则会报java.lang.UnsupportedOperationException异常,使用Set.of()不能出现重复元素、Map.of()不能出现重复key,不然回报java.lang.IllegalArgumentException。
。
Stream是Java 8 中的特性,在Java 9 中为其新增了4个方法:
ofNullable(T t)
此方法能够接收null来建立一个空流
之前 Stream.of(null); //报错 如今 Stream.ofNullable(null);
takeWhile(Predicate<? super T> predicate)
此方法根据Predicate接口来判断若是为true就 取出
来生成一个新的流,只要碰到false就终止,无论后边的元素是否符合条件。
Stream<Integer> integerStream = Stream.of(6, 10, 11, 15, 20); Stream<Integer> takeWhile = integerStream.takeWhile(t -> t % 2 == 0); takeWhile.forEach(System.out::println); // 6,10
dropWhile(Predicate<? super T> predicate)
此方法根据Predicate接口来判断若是为true就 丢弃
来生成一个新的流,只要碰到false就终止,无论后边的元素是否符合条件。
Stream<Integer> integerStream = Stream.of(6, 10, 11, 15, 20); Stream<Integer> takeWhile = integerStream.dropWhile(t -> t % 2 == 0); takeWhile.forEach(System.out::println); //11,15,20
iterate重载
之前使用iterate方法生成无限流须要配合limit进行截断
Stream<Integer> limit = Stream.iterate(1, i -> i + 1).limit(5); limit.forEach(System.out::println); //1,2,3,4,5
如今重载后这个方法增长了个判断参数
Stream<Integer> iterate = Stream.iterate(1, i -> i <= 5, i -> i + 1); iterate.forEach(System.out::println); //1,2,3,4,5
stream()
若是为空返回一个空流,若是不为空将Optional的值转成一个流。
//返回Optional值的流 Stream<String> stream = Optional.of("Java 11").stream(); stream.forEach(System.out::println); // Java 11 //返回空流 Stream<Object> stream = Optional.ofNullable(null).stream(); stream.forEach(System.out::println); //
ifPresentOrElse(Consumer<? super T> action, Runnable emptyAction)
我的感受这个方法就是结合isPresent()对Else的加强,ifPresentOrElse 方法的用途是,若是一个 Optional 包含值,则对其包含的值调用函数 action,即 action.accept(value),这与 ifPresent 一致;与 ifPresent 方法的区别在于,ifPresentOrElse 还有第二个参数 emptyAction —— 若是 Optional 不包含值,那么 ifPresentOrElse 便会调用 emptyAction,即 emptyAction.run()。
Optional<Integer> optional = Optional.of(1); optional.ifPresentOrElse( x -> System.out.println("Value: " + x),() -> System.out.println("Not Present.")); //Value: 1 optional = Optional.empty(); optional.ifPresentOrElse( x -> System.out.println("Value: " + x),() -> System.out.println("Not Present.")); //Not Present.
or(Supplier<? extends Optional<? extends T>> supplier)
Optional<String> optional1 = Optional.of("Java"); Supplier<Optional<String>> supplierString = () -> Optional.of("Not Present"); optional1 = optional1.or( supplierString); optional1.ifPresent( x -> System.out.println("Value: " + x)); //Value: Java optional1 = Optional.empty(); optional1 = optional1.or( supplierString); optional1.ifPresent( x -> System.out.println("Value: " + x)); //Value: Not Present
String lxs = "java"; try (var inputStream = new ByteArrayInputStream(lxs.getBytes()); var outputStream = new ByteArrayOutputStream()) { inputStream.transferTo(outputStream); System.out.println(outputStream); //java }
改api支持同步和异步两种方式,下面是两种方式的示例:
var request = HttpRequest.newBuilder() .uri(URI.create("https://www.baidu.com/")) .build(); var client = HttpClient.newHttpClient(); // 同步 HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.body()); // 异步 CompletableFuture<HttpResponse<String>> sendAsync = client.sendAsync(request, HttpResponse.BodyHandlers.ofString()); //这里会阻塞 HttpResponse<String> response1 = sendAsync.get(); System.out.println(response1.body());
咱们都知道之前要运行一个.java文件,首先要javac编译成.class文件,而后在java执行:
//编译 javac Java11.java //运行 java Java11
在java11中,只须要经过java一个命令就能够搞定
java Java11.java
许多运行在Java虚拟机中的应用程序(包括Apache Spark和Kafka等数据服务以及传统的企业应用程序)均可以在Docker容器中运行。可是在Docker容器中运行Java应用程序一直存在一个问题,那就是在容器中运行JVM程序在设置内存大小和CPU使用率后,会致使应用程序的性能降低。这是由于Java应用程序没有意识到它正在容器中运行。随着Java 10的发布,这个问题总算得以解决,JVM如今能够识别由容器控制组(cgroups)设置的约束。能够在容器中使用内存和CPU约束来直接管理Java应用程序,其中包括:
Java 10的这个改进在Docker for Mac、Docker for Windows以及Docker Enterprise Edition等环境均有效。
本人建立的java技术交流群,感兴趣的朋友能够扫码加入哦!
https://segmentfault.com/a/11...
感谢你们的观看,但愿多多关注哦。 若有错误,烦请指正。