本文列举了从Java8到11各个变化的API:
变量
从Java 10开始,开发人员可以选择让编译器使用var来推断类型:
<b>var</b> x=1.0/2.0 <b>var</b> list = <b>new</b> ArrayList<String>(); <b>var</b> stream = list.stream(); <font><i>// Type inference can be (Java 8)</i></font><font> Function helloFunction = s -> </font><font>"Hello "</font><font> + s; </font><font><i>// Inference of generics (Diamond Operator, since Java 7)</i></font><font> List strings = <b>new</b> ArrayList<>(); strings.add(helloFunction.apply(</font><font>"World"</font><font>)); </font><font><i>// Inference of generics (Diamond Operator) with anonymous inner classes (Java 9 -> JEP 213)</i></font><font> Consumer printer = <b>new</b> Consumer<>() { @Override <b>public</b> <b>void</b> accept(String string) { System.out.println(string); } }; strings.forEach(printer::accept); </font>
Java11已经提高了lambda中的var能力:
IntFunction<Integer> doubleIt1 = (<b>int</b> x) -> x * 2; <font><i>// OK Java 10 and 11</i></font><font> IntFunction<Integer> doubleIt2 = (<b>var</b> x) -> x * 2; </font><font><i>// OK Java 11</i></font><font> </font>
更复杂案例:
/ /Inference of parameters in Lambda expressions Consumer<String> printer = (<b>var</b> s) -> System.out.println(s); <font><i>// statt s -> System.out.println(s);</i></font><font> </font><font><i>// But no mixture of "var" and declarated types possible</i></font><font> </font><font><i>// BiConsumer<String, String> printer = (var s1, String s2) -> System.out.println(s1 + " " + s2);</i></font><font> </font><font><i>// Useful for type annotations</i></font><font> BiConsumer<String, String> printer = (@Non<b>null</b> <b>var</b> s1, @Nullable <b>var</b> s2) -> System.out.println(s1 + (s2 == <b>null</b> ? </font><font>""</font><font> : </font><font>" "</font><font> + s2)); </font><font><i>// given</i></font><font> Optional<String> value = Optional.of(</font><font>"properValue"</font><font>); AtomicInteger successCounter = <b>new</b> AtomicInteger(0); AtomicInteger onEmptyOptionalCounter = <b>new</b> AtomicInteger(0); </font><font><i>// when</i></font><font> value.ifPresentOrElse( v -> successCounter.incrementAndGet(), onEmptyOptionalCounter::incrementAndGet); </font>
String新方法
java 8加入新方法join:
Set<String> set1 = Set.of(<font>"a"</font><font>,</font><font>"b"</font><font>, </font><font>"c"</font><font>); List<String> list1 = List.of(</font><font>"a"</font><font>,</font><font>"b"</font><font>, </font><font>"c"</font><font>); System.out.println( String.join(</font><font>"a"</font><font>, </font><font>"b"</font><font>, </font><font>"c"</font><font>) ); System.out.println( String.join(</font><font>"."</font><font>, set1) ); System.out.println( String.join(</font><font>"."</font><font>, list1) ); </font>
Java9 有了一个返回Stream的新方法
Java11 添加了更多String的新方法:
String.repeat(<b>int</b>) String.lines() String.strip() String.stripLeading() String.stripTrailing() String.isBlank()
接口
java8:
Java9:
Java11:
看一个接口的完整代码:
<font><i>//generic interface with one type parameter T</i></font><font> <b>interface</b> SomeInterface<T> { <b>int</b> SOME_CONSTANT = 35; </font><font><i>// variable declaration</i></font><font> <b>int</b> abstractMethod(<b>int</b> x, <b>int</b> y); </font><font><i>// method declaration</i></font><font> T abstractMethodUsingGenericType(T[] array, <b>int</b> i); </font><font><i>// method using type parameter</i></font><font> <b>default</b> <b>int</b> <b>default</b>Method(<b>int</b> x, <b>int</b> y) { </font><font><i>// implementation of method</i></font><font> <b>return</b> 0; } <b>static</b> <b>void</b> main(String[] args) { </font><font><i>// any static method, including main can be included in interface</i></font><font> } <b>private</b> <b>void</b> <b>private</b>Method(String[] args) { </font><font><i>// any private method can be included in interface</i></font><font> } <b>private</b> <b>static</b> <b>void</b> <b>static</b>Method(String[] args) { </font><font><i>// any private static method can be included in interface</i></font><font> } </font><font><i>// nested class definition</i></font><font> <b>class</b> NestedClass { </font><font><i>// members of a class</i></font><font> } </font><font><i>// nested interface definition</i></font><font> <b>interface</b> NestedInterface { </font><font><i>// member of an interface</i></font><font> } </font><font><i>// nested enum definition</i></font><font> enum NestedEnum { OBJECT1, OBJECT2, ; </font><font><i>// methods, variables and constructors</i></font><font> } </font><font><i>// nested annotation definition</i></font><font> @<b>interface</b> NestedAnnotation { String attrib1(); } } </font>
Nullable管理
java8引入了新的Optional。
<font><i>// return an optional empty object</i></font><font> Optional<String> optional = Optional.empty(); </font><font><i>// return an optional with value object</i></font><font> String str = </font><font>"value"</font><font>; Optional<String> optional = Optional.of(str); </font><font><i>// return an optional with or without value </i></font><font> Optional<String> optional = Optional.ofNullable(getString()); </font><font><i>// how to solve String version = computer?.getSoundcard()?.getUSB()?.getVersion() ?: "UNKNOWN";</i></font><font> </font><font><i>// with map</i></font><font> String version = computer.flatMap(Computer::getSoundcard) .flatMap(Soundcard::getUSB) .map(USB::getVersion) .orElse(</font><font>"UNKNOWN"</font><font>); </font><font><i>//list</i></font><font> List<String> list = getList(); List<String> listOpt = list != <b>null</b> ? list : <b>new</b> ArrayList<>(); </font><font><i>// is equivalent to</i></font><font> List<String> listOpt = getList().orElseGet(() -> <b>new</b> ArrayList<>()); </font>
java9中可以返回另外一个Optional ,使用增强方法ifPresentOrElse :
String defaultString = <font>"default"</font><font>; Optional<String> value = Optional.empty(); Optional<String> defaultValue = Optional.of(defaultString); </font><font><i>// when</i></font><font> Optional<String> result = value.or(() -> defaultValue); </font><font><i>// given</i></font><font> Optional<String> value = Optional.of(</font><font>"properValue"</font><font>); AtomicInteger successCounter = <b>new</b> AtomicInteger(0); AtomicInteger onEmptyOptionalCounter = <b>new</b> AtomicInteger(0); </font><font><i>// when</i></font><font> value.ifPresentOrElse( v -> successCounter.incrementAndGet(), onEmptyOptionalCounter::incrementAndGet); </font>
也增加了stream方法。
Java10中有新的方法叫:orElseThrow
Java11中代码如下:
Optional.of(string).isEmpty()
Stream
Java8 引入了新的Stream:
<font><i>// starting from list</i></font><font> List<String> myList = Arrays.asList(</font><font>"a1"</font><font>, </font><font>"a2"</font><font>, </font><font>"b1"</font><font>, </font><font>"c2"</font><font>, </font><font>"c1"</font><font>); myList .stream() .filter(s -> s.startsWith(</font><font>"c"</font><font>)) .map(String::toUpperCase) .sorted() .forEach(System.out::println); </font><font><i>// native stream </i></font><font> Stream.of(</font><font>"a1"</font><font>, </font><font>"a2"</font><font>, </font><font>"a3"</font><font>) .findFirst() .ifPresent(System.out::println); </font>
可以和number和map一起运行:
<font><i>// working with number</i></font><font> IntStream.range(1, 4) .forEach(System.out::println); </font><font><i>// working with map</i></font><font> Arrays.stream(<b>new</b> <b>int</b>[] {1, 2, 3}) .map(n -> 2 * n + 1) .average() .ifPresent(System.out::println); </font>
流提供者可以多次重用流Stream,从而避免了集合中臭名昭著的错误:
java.lang.IllegalStateException: stream has already been operated upon or closed
Supplier<Stream<String>> streamSupplier = () -> Stream.of(<font>"d2"</font><font>, </font><font>"a2"</font><font>, </font><font>"b1"</font><font>, </font><font>"b3"</font><font>, </font><font>"c"</font><font>) .filter(s -> s.startsWith(</font><font>"a"</font><font>)); streamSupplier.get().anyMatch(s -> <b>true</b>); </font><font><i>// ok</i></font><font> streamSupplier.get().noneMatch(s -> <b>true</b>); </font><font><i>// ok</i></font><font> </font>
收集器可以转换到几种List:
List<Person> filtered = persons .stream() .filter(p -> p.name.startsWith(<font>"P"</font><font>)) .collect(Collectors.toList()); </font>
使用flatmap管理nullability
Outer <b>outer</b> = <b>new</b> Outer(); <b>if</b> (<b>outer</b> != <b>null</b> && <b>outer</b>.nested != <b>null</b> && <b>outer</b>.nested.<b>inner</b> != <b>null</b>) { System.out.println(<b>outer</b>.nested.<b>inner</b>.foo); } <font><i>// similar to类似上面代码的新写法</i></font><font> Optional.of(<b>new</b> Outer()) .flatMap(o -> Optional.ofNullable(o.nested)) .flatMap(n -> Optional.ofNullable(n.<b>inner</b>)) .flatMap(i -> Optional.ofNullable(i.foo)) .ifPresent(System.out::println); </font>
Java9中引入了iterate 和 takeWhile/dropWhile方法:
Stream.iterate(0, i -> i < 10, i -> i + 1) .forEach(System.out::println); System.out.println(<font>"stream take while"</font><font>); Stream<String> stream1 = Stream.iterate(</font><font>""</font><font>, s -> s + </font><font>"s"</font><font>) .takeWhile(s -> s.length() < 10); stream1.forEach(System.out::println); </font>
Java11引入了Not谓词,以前代码:
lines.stream() .filter(s -> !s.isBlank())
现在可以是:
lines.stream() .filter(Predicate.not(String::isBlank))
响应式Stream
Java9 引入了java.util.concurrent.Flow的四个接口:
还有不可变集合:
<font><i>// empty immutable collections</i></font><font> List<String> emptyImmutableList = List.of(); Set<String> emptyImmutableSet = Set.of(); Map emptyImmutableMap = Map.of(); </font><font><i>// immutable collections</i></font><font> List<String> immutableList = List.of(</font><font>"one"</font><font>, </font><font>"two"</font><font>); Set<String> immutableSet = Set.of(</font><font>"value1"</font><font>, </font><font>"value2"</font><font>); Map<String, String> immutableMap = Map.of(</font><font>"key1"</font><font>, </font><font>"Value1"</font><font>, </font><font>"key2"</font><font>, </font><font>"Value2"</font><font>, </font><font>"key3"</font><font>, </font><font>"Value3"</font><font>); </font>
Java9引入了MultiResolutionImage和提高了Process API
Java10提高了通过List.copyOf(), Set.copyOf(), Map.copyOf()创建不可变集合能力,Collectors类有了新方法toUnmodifiableList, toUnmodifiableSet, toUnmodifiableMap.
新语法
Java 9 try-with-resource现在支持内部可自定义:
<b>try</b> (<b>new</b> MyAutoCloseable() { }.finalWrapper.finalCloseable) { <font><i>// do some stuff with finalCloseable</i></font><font> } <b>catch</b> (Exception ex) { } </font>
Java 9 还支持带有菱形运算符的匿名类:
List<String> list = new ArrayList<>(){ };
Java 9 支持支持HTTP / 2和websockets的新HTTP客户端API。
Java 11 改善了HTTP客户端API支撑
<b>int</b> numLetters = <b>switch</b> (day) { <b>case</b> MONDAY, FRIDAY, SUNDAY -> 6; <b>case</b> TUESDAY -> 7; <b>case</b> THURSDAY, SATURDAY -> 8; <b>case</b> WEDNESDAY -> 9; };
Lambdas
Java8中已经引入了Lambda语法:s -> do(s)
为了支持Lambda,引入了5个接口:Consumer, Function, Supplier, Predicate, Operator
在Iterable & Stream & Optional上增加了几个方法:
Java 11提高了Lambda的var推断能力
Deprecated
Java 9 short list (https://docs.oracle.com/javase/9/docs/api/deprecated-list.html)
Java 11 short list
Java EE packages removed
日志
Java9提供了日志级别和作用域:
java -Xlog:all=debug:file=application.log -version
Annotations
Java 8
Java 9
has improved the following annotations