There may arise a situation where you need to create a class solely to hold data. In such cases, you can mark the class as data to create a data class. For example,
data class Person(val name: String, var age: Int)
For this class, the compiler automatically generates:
copy()function,equals()andhashCode()pair, andtoString()form of the primary constructorcomponentN()functions
Before talking about these features in detail, let's talk about requirements that a data class must fulfill.
Kotlin Data Class Requirements
Here are the requirements:
- The primary constructor must have at least one parameter.
 - The parameters of the primary constructor must be marked as either 
val(read-only) orvar(read-write). - The class cannot be open, abstract, inner or sealed.
 - The class may extend other classes or implement interfaces. If you are using Kotlin version before 1.1, the class can only implement interfaces.
 
Example: Kotlin Data Class
data class User(val name: String, val age: Int)
fun main(args: Array<String>) {
    val jack = User("jack", 29)
    println("name = ${jack.name}")
    println("age = ${jack.age}")
}
When you run the program, the output will be:
name = jack age = 29
When you declare a data class, the compiler automatically generates several functions such as toString(), equals(), hashcode() etc behind the scenes. This helps to keep you code concise. Had you used Java, you would need to write a lot of boilerplate code.
Let's use these functions:
Copying
For a data class, you can create a copy of an object with some of its properties different using copy() function. Here's how it works:
data class User(val name: String, val age: Int)
fun main(args: Array<String>) {
    val u1 = User("John", 29)
   
    // using copy function to create an object
    val u2 = u1.copy(name = "Randy")
    println("u1: name = ${u1.name}, name = ${u1.age}")
    println("u2: name = ${u2.name}, name = ${u2.age}")
}
When you run the program, the output will be:
u1: name = John, name = 29 u2: name = Randy, name = 29
toString() method
The toString() function returns a string representation of the object.
data class User(val name: String, val age: Int)
fun main(args: Array<String>) {
    val u1 = User("John", 29)
    println(u1.toString())
}
When you run the program, the output will be:
User(name=John, age=29)
hashCode() and equals()
The hasCode() method returns hash code for the object. If two objects are equal, hashCode() produces the same integer result. Recommended Reading: hashCode()
The equals() returns true if two objects are equal (has same hashCode()). If objects are not equal, equals() returns false. Recommended Reading: equals()
data class User(val name: String, val age: Int)
fun main(args: Array<String>) {
    val u1 = User("John", 29)
    val u2 = u1.copy()
    val u3 = u1.copy(name = "Amanda")
    println("u1 hashcode = ${u1.hashCode()}")
    println("u2 hashcode = ${u2.hashCode()}")
    println("u3 hashcode = ${u3.hashCode()}")
    if (u1.equals(u2) == true)
        println("u1 is equal to u2.")
    else
        println("u1 is not equal to u2.")
    if (u1.equals(u3) == true)
        println("u1 is equal to u3.")
    else
        println("u1 is not equal to u3.")
}
When you run the program, the output will be:
u1 hashcode = 71750738 u2 hashcode = 71750738 u3 hashcode = 771732263 u1 is equal to u2. u1 is not equal to u3.
Destructuring Declarations
You can destructure an object into a number of variables using destructing declaration. For example:
data class User(val name: String, val age: Int, val gender: String)
fun main(args: Array<String>) {
    val u1 = User("John", 29, "Male")
    val (name, age, gender) = u1
    println("name = $name")
    println("age = $age")
    println("gender = $gender")
}
When you run the program, the output will be:
name = John age = 29 gender = Male
This was possible because the compiler generates componentN() functions all properties for a data class. For example:
data class User(val name: String, val age: Int, val gender: String)
fun main(args: Array<String>) {
    val u1 = User("John", 29, "Male")
    println(u1.component1())     // John
    println(u1.component2())     // 29  
    println(u1.component3())     // "Male"
}
When you run the program, the output will be:
John 29 Male