Java SE 16 record 类型说明与使用

Java SE 16 record 类型说明与使用

作者:Grey

原文地址:

博客园:Java SE 16 record 类型说明与使用

CSDN:Java SE 16 record 类型说明与使用

说明

record 是 Java SE 16 的新特性

record 的使用场景

假设我们想创建一个不可变的类 Point,它有 x 和 y 的坐标。我们想实例化Point对象,读取它们的字段,并将它们存储在 List 中或在 Map 中作为键值使用。

我们可以这样实现 Point 类

public class Point {      private final int x;     private final int y;      @Override     public boolean equals(Object o) {         if (this == o) return true;         if (o == null || getClass() != o.getClass()) return false;          Point point = (Point) o;          if (x != point.x) return false;         return y == point.y;     }      @Override     public int hashCode() {         int result = x;         result = 31 * result + y;         return result;     }      @Override     public String toString() {         return "Point{" + "x=" + x + ", y=" + y + '}';     }      public Point(int x, int y) {         this.x = x;         this.y = y;     }       public int getX() {         return x;     }      public int getY() {         return y;     } } 

如上代码中重复写了很多模板代码,使用 Lombok,代码可以简化成如下方式

@AllArgsConstructor @Getter @EqualsAndHashCode @ToString public class Point {   private final int x;   private final int y; } 

现在有了 record 上述所有代码可以简化为

public record Point(int x, int y) {} 

使用javac Point.java && javap Point,我们可以查看到 Point 反编译后的结果

public final class Point extends java.lang.Record {   public Point(int, int);   public final java.lang.String toString();   public final int hashCode();   public final boolean equals(java.lang.Object);   public int x();   public int y(); } 

和我们最初始的 Point 类定义是一样的,所以 record 可以大量简化代码的编写。

我们可以像正常使用类一样使用 record

示例代码

public class App {     public static void main(String[] args) {         Point p = new Point(3, 4);         int x = p.x();         int y = p.y();         System.out.println(x + " " + y);           Point p2 = new Point(3, 4);         Point p3 = new Point(7, 5);          System.out.println(p2.equals(p)); // 输出 true         System.out.println(p2.equals(p3)); // 输出 false     } } 

record 可以通过如下方式来实现多构造函数

public record Point(int x, int y) {     public Point() {         this(3, 3);     }      public Point(int v) {         this(v, v + 3);     } } 

record 中可以包括 static 类型变量,示例如下

public record Point(int x, int y) {     private static final int ZERO = 0;     private static long count = 0;      public Point() {          this(ZERO, ZERO);         synchronized (Point.class) {             count++;         }     }     public static synchronized long getCount() {         return count;     }     public Point(int v) {         this(v, v + 3);     } } 

如果要覆盖 record 的默认构造函数,则函数入参一定要和 record 的入参保持一致,否则会报错

正确

public record Point(int x, int y) {     public Point(int x, int y) {         this.x = x;         this.y = y;     } } 

错误

public record Point(int x, int y) {     public Point(int m, int n) {         this.x = m;         this.y = n;     } } 

record 中可以自定义非 static 方法,例如

public record Point(int x, int y) {     public double distanceTo(Point target) {         int dx = target.x() - this.x();         int dy = target.y() - this.y();         return Math.sqrt(dx *dx + dy* dy);     } } 

调用方法

public class App {     public static void main(String[] args) {         Point from = new Point(17, 3);         Point to = new Point(18, 12);         double distance = from.distanceTo(to);         System.out.println(distance);     } }  

record 也可以实现接口,但是无法继承类

正确

 public record Point(int x, int y) implements WithXCoordinate {}  public interface WithXCoordinate {     int x(); }  

错误

public record Point(int x, int y) extends WithXCoordinate {}  public class WithXCoordinate {     int x(){} } 

record 也无法被其他类继承,例如

错误

public record Point(int x, int y)  {}  public class WithXCoordinate extends Point{     int x(){} } 

源码

hello-record

参考文档

Java Records

发表评论

评论已关闭。

相关文章