Source: From Java 8 to Java 15 in Ten Minutes | by Philipp Gysel | The Startup | Medium

 From Java8 to Java 15, Java now fully supports::
 
· Functional Programming (Java 8)
· Streams (Java 8)
· Optional (Java 8)
· JShell (Java 9)
· Factory Methods for Immutable Collections (Java 9)
· Type Inference with _var_ (Java 10)
· Single Source File Launch (Java 11)
· Switch Expression (Java 12: experimental, full feature: Java 14)
· Multi-line Strings (Java 13: experimental, full feature: Java 15)
· Data Classes(Data Classes: record (Java 14))
· _instanceof_ without Cast (Java 14: experimental)
· Sealed classes (Java 15: experimental)
· Bonus: Updated Licensing Terms Starting with Java 8
· Wrap up

Bonus: Updated Licensing Terms Starting with Java 8

意外收获,从Java 8开始更新的许可条款。

One last topic for this article: licensing. Most of you heard that Oracle stopped updates for Java 8 (for the free commercial version). So here are your options:
  • Use a newer Oracle JDK version (Oracle offers free security updates for only 6 months after each release)
    JdK官方在每个版本仅仅提供6个月的免费安全更新
  • Use and old JDK version at your own risk(风险自负)
    旧版本JDK风险自负
  • Use an old OpenJDK Java version, those still get security updates from the open source community or a third party vendor
    使用旧版本可以从第三方继续获取更新
  • Pay Oracle for premier support (e.g. Java 8: support until 2030)
    向Oracle支付以获得永久技术支持。
Oracle will bring out a new Java version every 6 months.

每6个月推出一个新的Java版本,通过实验更新来赶上其他现代编程语言。

Functional Programming (Java 8)

In Java 8, functional programming and lambdas were added as language features.

JDK8 中正式引入了 函数表达式。

The two core paradigms of functional programming are immutable values and elevating functions to first class citizens.

函数式编程的两个核心范式是:不可变的价值和将**函数提升为第一等公民。

Data goes through a pipeline of modification steps, where each step takes some input and maps it to a new output.

在函数式编程表达式中,数据被转化为流的概念,但是不同于传统意义的流,函数表达式的流更像是流水线

Streams (Java 8)

For your average computer program, you often have to work with a list of values and perform a given transformation on each value. Prior(先行) to Java 8, you had to use a for loop for this transformation(转变), but from now on, you can use Streams as follows:

在过去如果想要对于List进行操作,需要依赖循环完成转变,但是现在可以使用JAVA 8 的Stream。

The map function takes as input a lambda, which will be applied to all elements in the stream.

Map函数接受Lambada作为输入。

Streams can work on ListsSets, and Maps (via transformation).

Streams可以在Lists、Set、Map中进行操作

Stream.of("hello", "great")
.map(s -> s + " world")
.forEach(System.out::println);

> hello world
> great world

Optional

Another common problem in Java were Null Pointer Exceptions. So, Java introduced Optional — a monad that wraps a reference which might or might not be null

除了要面对大量的数据流处理的情况,另一种情况是空指针异常的处理,在对象层级嵌套非常频繁的情况下,所以Jdk8提供了Optional操作来帮助开发者处理空指针异常问题。

比如下面代码中设置Shiro关键的AES加密密钥,下面的案例采用了数据库存储,从数据库读取,如果数据库读不到值,可以写死一个内部变量防止报错,当然这里更建议在没有配置的时候打印warn日志进行提示。

// 防止为空,增加默认随机AES对称密钥  
String shiroValue = Optional.ofNullable(shiroConfig).map(ShiroConfig::getShiroValue).orElse("xxxxxxxx");

当然,我们也可以利用Optional 做更多灵活操作:

Optional.of(new Random().nextInt(10))
.filter(i -> i % 2 == 0)
.map(i -> "number is even: " + i)
.ifPresent(System.out::println);
> number is even: 6
In the snippet above, we create a random number, wrap it inside an Optional object, and then only print the number if it is even(偶数).

在上面的片段中,我们创建了一个随机数,将其包裹在一个Optional对象中,然后只在偶数时打印该数字。

Jshell

Finally, we have a REPL for Java, and its name is JShell!😊 In a nutshell, JShell allows to experiment with Java snippets without writing and compiling a full Java class. Instead, you can execute one command at a time, and you immediately see the result. Here’s a simple example:

在JDK9中终于有REPL命令行工具了,算是和现代主流编程语言靠拢,可以再Jshell中直接输入JAVA表达式。真正实现一次只执行一条命令。

但是因为这是个锦上添花的玩意,用的不多,这里仅仅做一些简单演示:

jshell> 3+1
$1 ==> 4
jshell> 13%7
$2 ==> 6
jshell> $2
$2 ==> 6
jshell>

Oracle 的官方简单介绍:https://docs.oracle.com/javase/9/jshell/introduction-jshell.htm#JSHEL-GUID-630F27C8-1195-4989-9F6B-2C51D46F52C8

JShell allows to define variables, but also more complex entities like multi-line functions, classes, and perform loops. Moreover, JShell supports auto-completion, which comes in handy if you don’t know the exact methods offered by a given Java class.

JShell允许定义变量,但也允许更复杂的实体,如多行函数执行循环。此外,JShell支持自动补全,如果你不知道一个给定的Java类所提供的确切方法,它就会很方便。

Factory Methods for Immutable Collections (Java 9)

不可变对象的工厂方法。

Simple initialization of Lists has been missing in Java for a long time, but those times are over now. 😅 Previously you had to do something like this:

简单的集合初始化在Jdk9中出现。现在Arrays.asList 可以使用List.of替换。

jshell> List<Integer> list = Arrays.asList(1, 2, 3, 4)
list ==> [1, 2, 3, 4]
jshell> List<Integer> list = List.of(1, 2, 3, 4)

b ==> [1, 2, 3, 4]
This fancy of(...) method exists for ListSet and Map.

Type Inference with var (Java 10)

Java 10 introduced the new var keyword which allows to omit the type(省略类型) of a variable.

jdk10 出现了 var关键字允许省略类型的变量定义。

jshell> var x = new HashSet<String>()
x ==> []

jshell> x.add("apple")
$1 ==> true
In the snippet(片段) above, the type of x can be inferred to be HashSet by the compiler.

Single Source File Launch (Java 11)

Switch Expression (Java 12)

Java 12 brought us Switch expressions. Here’s a quick showcase of how the expression differs from the old switch statement.

JDK 12 带来了Switch 表达式,下面是和旧版本的区别:

jshell> var i = 3

jshell> String s;

jshell> switch(i) {

...> case 1: s = "one"; break;

...> case 2: s = "two"; break;

...> case 3: s = "three"; break;

...> default: s = "unknown number";

...> }

jshell> s

s ==> "three"

jshell> var i = 3;

jshell> var x = switch(i) {

...> case 1 -> "one";

...> case 2 -> "two";

...> case 3 -> "three";

...> default -> "unknown number";

...> };

x ==> "three"
Java has gone a long way in the last 6 years, there have actually been 8 new Java releases since then!

旧版本的Switch仅仅是一个处理流,但是再新版本中可以作为返回值解析。

Notice that this new switch statement is a sort of mapping function

注意新版本的Switch可以看作是一个映射函数

This is actually a pattern matching feature which helps to make Java more compatible with the functional programming principles

新版的Switch实际上算是一种模式匹配功能,有助于使Java与函数式编程原则更加兼容。

Multi-line Strings (Java 13)

So far, you’d probably squash everything on one line and use newline characters \n, but this makes the String much harder to read.

再很多时候如果想要给JAVA字符串换行是非常麻烦的,因为需要加入大量的\n,这会导致代码难以阅读。

A couple of things to note:

  • Instead of double points, we use arrows ->
  • There’s no need for break
  • The default case can be omitted when all possible cases are considered
  • To enable this feature with Java 12, use --enable-preview --source 12

值得注意的一些事:

  1. 使用箭头函数。
  2. 新版switch不需要break。
  3. 尽可能考虑所有情况,可以省略default的写法.
  4. 要想在JDK12生效,可以使用启动参数--enable-preview --source 12

JDK 13开始允许下面的写法:

Sample case:
public class Main {

public static void main(String [] args) {

var s = """

{

"recipe": "watermelon smoothie",

"duration": "10 mins",

"items": ["watermelon", "lemon", "parsley"]

}""";

System.out.println(s);

}

}

Sealed classes (Java 15)

jdk15出现了密封对象。

With the sealed keyword, you can restrict which classes can extend a given class or interface.

所谓的密封对象通常用在接口上,用于限制接口的实现或者继承者,只有被密封对象声明的类可以使用此接口。

给个案例更为直观:

public sealed interface Fruit permits Apple, Pear {

    String getName();

}

public final class Apple implements Fruit {

    public String getName() { return "Apple"; }

}

public final class Pear implements Fruit {

    public String getName() { return "Pear"; }

}
Now you know how many Fruits there are. This is actually an important step into the direction fully supported pattern matching, where you can sort of treat classes like enums

密封类的出现使得类可以被当作枚举一样被对待,在使用设计模式的情况下,这一个密封特性会非常有用。

This sealed feature goes together nicely with the new switch expression explained previously.

这个语法和新的switch表现形式可以更好的结合。

instanceof without Cast (Java 14)

Object obj = new String("hello");

if (obj instanceof String) {

System.out.println("String length: " + ((String)obj).length());

}
The unfortunate part: First we check that s is of type String, then we cast it again to retrieve its length.

在传统的instanceof 操作当中,我们经常需要先判断对象类型,然后还需要把Object对象进行强转,这会产生大量不美观的强转代码。

Now with Java 14, the compiler is smart enough to infer the type automatically after the instanceof check:

现在JDK 14 的编译器支持自动检查instanceof 的对象类型,并且可以直接定义,省略了强转的操作:

Object obj = new String("hello");

if (obj instanceof String mystr) {

System.out.println("String length: " + mystr.length());

}

Data Classes: record (Java 14)

finally, there are data classes in Java! These classes are declared with the record keyword and have automatic Getters, a constructor, and equals() method etc. In short, you can get rid of a huge chunk of boilerplate code!

JDK14引入了数据类,这些类用record关键字声明,并有自动的Getters、构造函数和equals()方法等。简而言之,你可以摆脱一大块模板代码了

jshell> record Employee (String name, int age, String department) {}

| created record Employee

jshell> var x = new Employee("Anne", 25, "Legal");

x ==> Employee[name=Anne, age=25, department=Legal]

jshell> x.name()

$2 ==> "Anne"

Finally

I had a blast writing this article🔥 Thanks for reading😊 What’s your favorite feature in a recent java release? I’d love to get a feedback from you! Cheers!

我在写这篇文章时很开心,谢谢你的阅读😊 在最近的JAVA版本中,你最喜欢的功能是什么?我很想得到你的反馈! 干杯!


Xander
201 声望53 粉丝