<aside> 💡 자바 코드는 쓸데 없이 장황하다! ⇒ 바꿔 보자!
</aside>
자바에서 좌표 평면 상의 위치를 표현하기 위한 클래스인 Point 클래스를 작성한다고 해보자. 당연히 내부에 x 와 y 좌표를 나타내는 필드 변수가 있을 것이다. 또한, 올바른 동등 비교를 위해서는 equals와 hashCode도 재정의해야 한다. 그리고 단순히 좌표 값들을 전달하는 용도로 Point를 사용한다면 getter도 정의해야 한다. 따라서, 아래와 같은 코드가 작성된다.
class Point {
private final int x;
private final int y;
Point(int x, int y) {
this.x = x;
this.y = y;
}
int x() { return x; }
int y() { return y; }
public boolean equals(Object o) {
if (!(o instanceof Point)) return false;
Point other = (Point) o;
return other.x == x && other.y == y;
}
public int hashCode() {
return Objects.hash(x, y);
}
public String toString() {
return String.format("Point[x=%d, y=%d]", x, y);
}
}
이런 코드에는 몇가지 문제가 있다.
이런 문제를 “간결한 코드”로 해결 하기 위해 Record가 추가되었다.
<aside> 💡 Record 는 단순한 값의 집합을 표현하는 클래스를 작성하는데 사용하는 것이 좋다.
</aside>
record([매개변수 타입] 매개변수 명, ...) {
}
예를 들어 앞선 Point 클래스를 Record로 변경한다면 다음과 같은 코드로 작성할 수 있다.
record Point(int x, int y) {
}
위와 같이 작성하면, 아래의 코드와 동일하게 동작한다.
import java.util.Objects;
public final class Point {
private final int x;
private final int y;
public Point(int x, int y) {
this.x = x;
this.y = y;
}
public int x() {
return x;
}
public int y() {
return y;
}
@Override
public boolean equals(Object obj) {
if (obj == this) return true;
if (obj == null || obj.getClass() != this.getClass()) return false;
var that = (Point) obj;
return this.x == that.x &&
this.y == that.y;
}
@Override
public int hashCode() {
return Objects.hash(x, y);
}
@Override
public String toString() {
return "Point[" +
"x=" + x + ", " +
"y=" + y + ']';
}
}
<aside> ⚠️ 일반적인 클래스와 다르게, Record에 생성자를 추가하지 않는다면, 선언부에 적은 모든 필드를 매개변수로 하는 생성자가 자동으로 추가된다.
</aside>
VO를 생성할 때, 값에 대한 검증을 하는 경우가 있다. 이를 간편하게 하기 위해 compact 생성자를 추가할 수 있다.