class
앞에 value
키워드를 선언해주면 된다.val
이어야만 한다.@JvmInline
을 선언해줘야한다.value class
호환을 위해서 존재하는 Annotation@JvmInline
value class Age(val value: Int) {
infix fun isOrderThan(age: Age): Boolean {
return value > age.value
}
}
value class
로 선언하여 사용하면 메모리를 최적화하여 사용할 수 있다.value class
를 선언한 VO 를 사용하면 바이트 코드 상에서 VO 객체를 생성하지 않고 내부 프로퍼티를 직접 사용하여 VO 객체 생성에 따른 메모리 비용을 최적화 할 수 있다.value class
를 선언하면 내부적으로 equals()
, hashcode()
, toString()
메서드를 자동 생성해준다.inline class
와 같다.value class
로 이름도 바꾸고 딱 VO 객체 최적화를 위해서 사용하라고 만든 키워드이다.value class
를 사용할 수 있다.value class
를 선언한 VO 인 Age 클래스를 사용하는 Person 클래스class Person(val name: String, val age: Age) {
fun introduce() {
println("Hi, I'm $name my age is ${age.value}")
}
}
@JvmInline
value class Age(val value: Int) {
init {
check(value > 0)
}
infix fun isOrderThan(age: Age): Boolean {
return value > age.value
}
}
fun main() {
val age20 = Age(20)
val age19 = Age(19)
println(age20 isOrderThan age19) // 결과 : ture
}
value class
로 구현했다.public final class Person {
@NotNull
private final String name;
private final int age;
public final void introduce() {
String var1 = "Hi, I'm " + this.name + " my age is " + this.age;
System.out.println(var1);
}
@NotNull
public final String getName() {
return this.name;
}
public final int getAge_3KwQcjU/* $FF was: getAge-3KwQcjU*/() {
return this.age;
}
private Person(String name, int age) {
this.name = name;
this.age = age;
}
// $FF: synthetic method
public Person(String name, int age, DefaultConstructorMarker $constructor_marker) {
this(name, age);
}
}
@JvmInline
public final class Age {
private final int value;
public final int getValue() {
return this.value;
}
// $FF: synthetic method
private Age(int value) {
this.value = value;
}
public static final boolean isOrderThan_Ue8C4z0/* $FF was: isOrderThan-Ue8C4z0*/(int $this, int age) {
return $this > age;
}
public static int constructor_impl/* $FF was: constructor-impl*/(int value) {
boolean var1 = value > 0;
if (!var1) {
String var2 = "Check failed.";
throw new IllegalStateException(var2.toString());
} else {
return value;
}
}
// $FF: synthetic method
public static final Age box_impl/* $FF was: box-impl*/(int v) {
return new Age(v);
}
public static String toString_impl/* $FF was: toString-impl*/(int var0) {
return "Age(value=" + var0 + ")";
}
public static int hashCode_impl/* $FF was: hashCode-impl*/(int var0) {
return Integer.hashCode(var0);
}
public static boolean equals_impl/* $FF was: equals-impl*/(int var0, Object var1) {
if (var1 instanceof Age) {
int var2 = ((Age)var1).unbox-impl();
if (var0 == var2) {
return true;
}
}
return false;
}
public static final boolean equals_impl0/* $FF was: equals-impl0*/(int p1, int p2) {
return p1 == p2;
}
// $FF: synthetic method
public final int unbox_impl/* $FF was: unbox-impl*/() {
return this.value;
}
public String toString() {
return toString-impl(this.value);
}
public int hashCode() {
return hashCode-impl(this.value);
}
public boolean equals(Object var1) {
return equals-impl(this.value, var1);
}
}
public final class ValueClassTestKt {
public static final void main() {
int age20 = Age.constructor-impl(20);
int age19 = Age.constructor-impl(19);
boolean var2 = Age.isOrderThan-Ue8C4z0(age20, age19);
System.out.println(var2); // 결과 : ture
}
}
Age age
가 아니라 내부 프로퍼티 타입인 int age
가 선언되어있다. private final int age;
int
로 unboxing 되어 할당된다.int age20 = Age.constructor-impl(20);
int age19 = Age.constructor-impl(19);
equals()
, hashcode()
, toString()
메서드가 생성되어있다.