logo头像

From zero to HERO

Java 14 新特性之JEP 359 Records(Preview)

本文于 1356 天之前发表,文中内容可能已经过时。

1. 前言

本月(2020-03) Java 14 就该正式发布了,有一个 Java 社区呼唤已久的特性将作为 preview feature包含在 Java 14 中 ,这就是 JEP 359: Records。换句话说效果类似 lombok@Data 注解,但是又不完全是, 在合适的场景中我们终于不用编写样板代码了。今天我们就来感受一下。

其实更像 Jvm 语言 kotlin 中的 data class

2. 传统数据类

我们先来看看现在我们如何声明一个数据类:

public class Range {

    private final int min;
    private final int max;

    public Range(int min, int max) {
        this.min = min;
        this.max = max;
    }

    public int getMin() {
        return min;
    }

    public int getMax() {
        return max;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Range range = (Range) o;
        return min == range.min && max == range.max;
    }

    @Override
    public int hashCode() {
        return Objects.hash(min, max);
    }

    @Override
    public String toString() {
        return "Range{" +
          "min=" + min +
          ", max=" + max +
          '}';
    }
}

我们来看看这个类的特点:

  • 没有无参构造方法,需要初始化时对成员变量赋值
  • 成员变量只有 getter 方法。
  • 覆写了 超类 ObjectequalshashCodetoString 方法。

虽然我们可以借助于第三方框架或者 IDE 很容易编写这些样板代码,但是总归要写这些样板代码不是吗?

3. 新的 Java Records

上面的冗长的代码在 Java 14 中我们可以这么写:

public record Range(int min, int max) {}

没错就是这个简单!这个语法糖是不是有 “卧槽” 的感觉?我们声明这种类使用 record 标识(目前不知道 record 会不会上升到关键字的高度)。当你用 record 声明一个类时,该类将自动拥有以下功能:

  • 获取成员变量的简单方法,以上面代码为例 min()max() 。注意区别于我们平常getter的写法。
  • 一个 equals 方法的实现,执行比较时会比较该类的所有成员属性
  • 重写 equals 当然要重写 hashCode
  • 一个可以打印该类所有成员属性的 toString 方法。
  • 请注意只会有一个构造方法。

因为这个特性是 preview feature,默认情况下是无法编译和执行的。同样以上面为例我们需要执行:

 $ javac -d classes --enable-preview --release 14 Range.java
 $ java -classpath classes --enable-preview Range

Jshell 中运行

jshell> Range r = new Range(10, 20);
r ==> Range[min=10, max=20]

jshell> r.min()
$5 ==> 10

jshell> r.toString()
$6 ==> "Range[min=10, max=20]"

jshell> r
r ==> Range[min=10, max=20]

虽然 record 声明的类没有 final 关键字,实际上它是一个不可变类。除了一些限制外,它依旧是一个普通的Java 类。因此,我们可以像添加普通类一样添加逻辑。我们可以在构造实例时强制执行前提条件:

public record Range(int min, int max) {
    public Range { 
        if (min >= max) 
            throw new IllegalArgumentException("min should be less than max");
    }
}

另外我们也可以给 Records 类增加普通方法、静态属性、静态方法,这里不再举例;

为了简化语法糖的推理,不能在类内声明成员属性。以下是错误的示范:

public record Range(int min, int max) {
    // 错误的示范 
    private String name;
}

4. 总结

今天对即将到来的 Java 14 的预览特性 Java Records 进行了介绍。随着 Java 版本迭代的加快,Java 也逐渐跟上了时代的步伐,希望这门伟大的语言继续焕发生机。更多我的技术文章请访问 felord.cn

评论系统未开启,无法评论!