从 java 8到 java 11变化一览


本文列举了从Java8到11各个变化的API:

变量
从Java 10开始,开发人员可以选择让编译器使用var来推断类型:

var x=1.0/2.0

var list = new ArrayList<String>();  

var stream = list.stream();


// Type inference can be (Java 8)
Function helloFunction = s ->
"Hello " + s;
 
// Inference of generics (Diamond Operator, since Java 7)
List strings = new ArrayList<>();
strings.add(helloFunction.apply(
"World"));
 
// Inference of generics (Diamond Operator) with anonymous inner classes (Java 9 -> JEP 213)
Consumer printer = new Consumer<>() {
    @Override
    public void accept(String string) {
        System.out.println(string);
    }
};
strings.forEach(printer::accept);

Java11已经提高了lambda中的var能力:

IntFunction<Integer> doubleIt1 = (int x) -> x * 2; // OK Java 10 and 11
IntFunction<Integer> doubleIt2 = (var x) -> x * 2;
// OK Java 11

更复杂案例:

/ /Inference of parameters in Lambda expressions
Consumer<String> printer = (var s) -> System.out.println(s); // statt s -> System.out.println(s);
 
// But no mixture of "var" and declarated types possible
// BiConsumer<String, String> printer = (var s1, String s2) -> System.out.println(s1 + " " + s2);
 
// Useful for type annotations
BiConsumer<String, String> printer = (@Nonnull var s1, @Nullable var s2) -> System.out.println(s1 + (s2 == null ?
"" : " " + s2));

// given
Optional<String> value = Optional.of(
"properValue");
AtomicInteger successCounter = new AtomicInteger(0);
 
AtomicInteger onEmptyOptionalCounter = new AtomicInteger(0);
 
// when
value.ifPresentOrElse(
   v -> successCounter.incrementAndGet(), 
   onEmptyOptionalCounter::incrementAndGet);

String新方法
java 8加入新方法join:

Set<String> set1 = Set.of("a","b", "c");
List<String> list1 = List.of(
"a","b", "c");
  
System.out.println( String.join(
"a", "b", "c") );
System.out.println( String.join(
".", set1) );
System.out.println( String.join(
".", list1) );

Java9 有了一个返回Stream的新方法
Java11 添加了更多String的新方法:

String.repeat(int)
String.lines()
String.strip()
String.stripLeading()
String.stripTrailing()
String.isBlank()

接口
java8:

  1. 常量Constant variables
  2. 抽象方法Abstract methods
  3. 默认方法Default methods
  4. 静态方法Static methods

Java9:
  1. Constant variables
  2. Abstract methods
  3. Default methods
  4. Static methods
  5. 私有方法Private methods
  6. 私有静态方法Private Static methods

Java11:
看一个接口的完整代码:

//generic interface with one type parameter T
interface SomeInterface<T> { 
 int SOME_CONSTANT = 35;
// variable declaration
 int abstractMethod(int x, int y);  
// method declaration
 T abstractMethodUsingGenericType(T[] array, int i);
// method using type parameter
 default int defaultMethod(int x, int y) {
     
// implementation of method
  return 0;
 }
 static void main(String[] args) {
     
// any static method, including main can be included in interface
 }
 
 
 private void privateMethod(String[] args) {
     
// any private  method can be included in interface
 }
 
 private static void staticMethod(String[] args) {
     
// any private static method can be included in interface
 }
 
 
// nested class definition
 class NestedClass { 
     
// members of a class
 }
 
// nested interface definition
 interface NestedInterface { 
     
// member of an interface
 }
// nested enum definition
 enum NestedEnum {   
     OBJECT1,
     OBJECT2,
     ;
     
// methods, variables and constructors
 }
 
// nested annotation definition
 @interface NestedAnnotation {   
     String attrib1();
 }
}

Nullable管理
java8引入了新的Optional。

// return an optional empty object
Optional<String> optional = Optional.empty();

// return an optional with value object
String str =
"value";
Optional<String> optional = Optional.of(str);

// return an optional with or without value 
Optional<String> optional = Optional.ofNullable(getString());
// how to solve String version = computer?.getSoundcard()?.getUSB()?.getVersion() ?: "UNKNOWN";
// with map
String version = computer.flatMap(Computer::getSoundcard)
                            .flatMap(Soundcard::getUSB)
                            .map(USB::getVersion)
                            .orElse(
"UNKNOWN");
//list

List<String> list = getList();
List<String> listOpt = list != null ? list : new ArrayList<>();

// is equivalent to
List<String> listOpt = getList().orElseGet(() -> new ArrayList<>());

java9中可以返回另外一个Optional ,使用增强方法ifPresentOrElse :

String defaultString = "default";
Optional<String> value = Optional.empty();
Optional<String> defaultValue = Optional.of(defaultString);

// when
Optional<String> result = value.or(() -> defaultValue);


// given
Optional<String> value = Optional.of(
"properValue");
AtomicInteger successCounter = new AtomicInteger(0);
 
AtomicInteger onEmptyOptionalCounter = new AtomicInteger(0);
 
// when
value.ifPresentOrElse(
   v -> successCounter.incrementAndGet(), 
   onEmptyOptionalCounter::incrementAndGet);

也增加了stream方法。
Java10中有新的方法叫:orElseThrow
Java11中代码如下:
Optional.of(string).isEmpty()

Stream
Java8 引入了新的Stream:

// starting from list
List<String> myList =
    Arrays.asList(
"a1", "a2", "b1", "c2", "c1");

myList
    .stream()
    .filter(s -> s.startsWith(
"c"))
    .map(String::toUpperCase)
    .sorted()
    .forEach(System.out::println);

// native stream 
Stream.of(
"a1", "a2", "a3")
    .findFirst()
    .ifPresent(System.out::println);

可以和number和map一起运行:

// working with number
IntStream.range(1, 4)
    .forEach(System.out::println);

// working with map
Arrays.stream(new int[] {1, 2, 3})
    .map(n -> 2 * n + 1)
    .average()
    .ifPresent(System.out::println);

流提供者可以多次重用流Stream,从而避免了集合中臭名昭著的错误:

java.lang.IllegalStateException: stream has already been operated upon or closed

Supplier<Stream<String>> streamSupplier =
    () -> Stream.of("d2", "a2", "b1", "b3", "c")
            .filter(s -> s.startsWith(
"a"));

streamSupplier.get().anyMatch(s -> true);  
// ok
streamSupplier.get().noneMatch(s -> true);  
// ok

收集器可以转换到几种List:

List<Person> filtered =
    persons
        .stream()
        .filter(p -> p.name.startsWith("P"))
        .collect(Collectors.toList());

使用flatmap管理nullability 

Outer outer = new Outer();
if (outer != null && outer.nested != null && outer.nested.inner != null) {
    System.out.println(outer.nested.inner.foo);
}

// similar to类似上面代码的新写法
Optional.of(new Outer())
    .flatMap(o -> Optional.ofNullable(o.nested))
    .flatMap(n -> Optional.ofNullable(n.inner))
    .flatMap(i -> Optional.ofNullable(i.foo))
    .ifPresent(System.out::println);

Java9中引入了iterate 和 takeWhile/dropWhile方法:

Stream.iterate(0, i -> i < 10, i -> i + 1) .forEach(System.out::println);
System.out.println("stream take while");


Stream<String> stream1 = Stream.iterate(
"", s -> s + "s")
      .takeWhile(s -> s.length() < 10);
  
stream1.forEach(System.out::println);

Java11引入了Not谓词,以前代码:

lines.stream()          
         .filter(s -> !s.isBlank())

现在可以是:

lines.stream()          
         .filter(Predicate.not(String::isBlank))

响应式Stream
Java9 引入了java.util.concurrent.Flow的四个接口:

  • Flow.Processor
  • Flow.Publisher
  • Flow.Subscriber
  • Flow.Subscription

还有不可变集合:

// empty immutable collections
 List<String> emptyImmutableList = List.of();
 Set<String> emptyImmutableSet = Set.of();
 Map emptyImmutableMap = Map.of();

// immutable collections
List<String> immutableList = List.of(
"one", "two");
Set<String> immutableSet = Set.of(
"value1", "value2");
Map<String, String> immutableMap = Map.of(
"key1", "Value1", "key2", "Value2", "key3", "Value3");

Java9引入了MultiResolutionImage和提高了Process  API

Java10提高了通过List.copyOf(), Set.copyOf(), Map.copyOf()创建不可变集合能力,Collectors类有了新方法toUnmodifiableList, toUnmodifiableSet, toUnmodifiableMap.


新语法

Java 9 try-with-resource现在支持内部可自定义:

try (new MyAutoCloseable() { }.finalWrapper.finalCloseable) {
     // do some stuff with finalCloseable
  } catch (Exception ex) { }

Java 9还支持带有菱形运算符的匿名类:

List<String> list = new ArrayList<>(){ };

Java 9支持支持HTTP / 2和websockets的新HTTP客户端API。
Java 11改善了HTTP客户端API支撑

int numLetters = switch (day) {
    case MONDAY, FRIDAY, SUNDAY -> 6;
    case TUESDAY                -> 7;
    case THURSDAY, SATURDAY     -> 8;
    case WEDNESDAY              -> 9;
};

Lambdas
Java8中已经引入了Lambda语法:s -> do(s)
为了支持Lambda,引入了5个接口:Consumer, Function, Supplier, Predicate, Operator 
在Iterable & Stream & Optional上增加了几个方法:

  • forEach
  • filter
  • map
  • flatMap
  • collect
  • ...

Java 11提高了Lambda的var推断能力

Deprecated
Java 9 short list (https://docs.oracle.com/javase/9/docs/api/deprecated-list.html)

  1. java.activation
  2. java.corba
  3. java.se.ee
  4. java.transaction
  5. java.xml.bind
  6. java.xml.ws
  7. java.xml.ws.annotation
  8. jdk.policytool

Java 11 short list
Java EE packages removed
  • javax.activation (java.activation)
  • javax.activity, javax.rmi, javax.rmi.CORBA, org.omg.* (java.corba)
  • javax.transaction (java.transaction)
  • javax.xml.bind.* (java.xml.bind)
  • javax.jws, javax.jws.soap, javax.xml.soap, javax.xml.ws.*(java.xml.ws)
  • javax.annotation (java.xml.ws.annotation)

日志
Java9提供了日志级别和作用域:

java -Xlog:all=debug:file=application.log -version

Annotations
Java 8

  • @FunctionalInterface : to specify an interface "for lambda" purpose

Java 9
has improved the following annotations
  • @SafeVarargs : it improves now private methods
  • @Deprecated : it provide the scope of deprecation (JSCOR-GUID-BB859EA8-E6F7-4239-9A52-4F1BDE27BB09>https://docs.oracle.com/javase/9/core/enhanced-deprecation1.htmJSCOR-GUID-BB859EA8-E6F7-4239-9A52-4F1BDE27BB09)

var 到底有什么用

var 吸取动态类型js等优点,运行时再确定类型,而不是编码时过早确定类型,有些人害怕过度设计。

可叹,以后要是有人写了bug,只能在运行时才能发现了,编译时都不一定能找得出问题

var 丝毫不会影响Java对一个静态类型的归类,它做的,仅仅是在编译器中推断出变量类型,然后将实际的类型写入字节码,就像以往的强类型显式声明一样。
var str = "hello";
str = str * 2;
编译器会报红叉的。