We can use inline value classes to make a wrapper around some type with ❗no performance overhead (Item 47: Avoid unnecessary object creation). Two especially popular uses of inline value classes are:
To indicate a unit of measure.
To use types to protect users from value misuse.
@JvmInlinevalueclassName(privatevalvalue: String) {fungreet() {print("Hello, I am $value") }}// Codeval name: Name=Name("Marcin")// During compilation replaced with code similar to:// Such a class will be replaced with the value it holds whenever possible:val name: String="Marcin"//-------------------// Codename.greet()// During compilation replaced with code similar to: STATIC methodsName.`greet-impl`(name)
JPA Entities
In SQL databases, we often identify elements by their IDs, which are all just numbers. For instance, let’s say that you have a student’s grade in a system, which will probably need to reference the id of a student, teacher, school, etc:
The problem is that it is really easy to later misuse all these ids, and the type system does not protect us because they are all of type Int. The solution is to wrap all these integers into separate inline value classes:
Now those id uses will be safe and the database will be generated correctly because all these types will be replaced with Int anyway during compilation. This way, inline value classes allow us to introduce types where they were not allowed before; thanks to this, we have safer code with no performance overhead.
@Entity(tableName = "grades")
class Grades(
@ColumnInfo(name = "studentId")
val studentId: Int,
@ColumnInfo(name = "teacherId")
val teacherId: Int,
@ColumnInfo(name = "schoolId")
val schoolId: Int,
// ...
)
@JvmInline
value class StudentId(val studentId: Int)
@JvmInline
value class TeacherId(val teacherId: Int)
@JvmInline
value class SchoolId(val studentId: Int)
@Entity(tableName = "grades")
class Grades(
@ColumnInfo(name = "studentId")
val studentId: StudentId,
@ColumnInfo(name = "teacherId")
val teacherId: TeacherId,
@ColumnInfo(name = "schoolId")
val schoolId: SchoolId,
// ...
)