1. Overview
In this article, we will discuss the Kotlin data class and its auto-generated toString method. The primary purpose of this data class is to hold data and don’t provide any other functionality. Kotlin generates necessary utility functions for this class.
2. POJO class in Kotlin
You would have created classes only to hold data with no functionality. In Java, you call it POJO (Plain Old Java Object). You should have also written utility functions like getters, setters, toString
, constructors, and hashcode
methods for those classes.
Let’s take an example for the POJO class.
Suppose you have a feedback screen in your application to collect feedback from users. For this, you would create a plain Java class to get the user feedback and validate any SQL injection before storing it in the database.
package com.tedblob.data; public class UserFeedback { private String name; private String emailId; private String comments; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getEmailId() { return emailId; } public void setEmailId(String emailId) { this.emailId = emailId; } public String getComments() { return comments; } public void setComments(String comments) { this.comments = comments; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((comments == null) ? 0 : comments.hashCode()); result = prime * result + ((emailId == null) ? 0 : emailId.hashCode()); result = prime * result + ((name == null) ? 0 : name.hashCode()); return result; } public UserFeedback(String name, String emailId, String comments) { super(); this.name = name; this.emailId = emailId; this.comments = comments; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; UserFeedback other = (UserFeedback) obj; if (comments == null) { if (other.comments != null) return false; } else if (!comments.equals(other.comments)) return false; if (emailId == null) { if (other.emailId != null) return false; } else if (!emailId.equals(other.emailId)) return false; if (name == null) { if (other.name != null) return false; } else if (!name.equals(other.name)) return false; return true; } @Override public String toString() { return "UserFeedback [name=" + name + ", emailId=" + emailId + ", comments=" + comments + "]"; } }
Our requirement is to hold only the feedback data. But note that we have a lot of boilerplate code like toString
, hashcode
, equals
, getters, setter
methods in this class. Usually, you would use your IDE to generate them or manually write them.
You can avoid this much code in Kotlin using the data class. It looks concise and clean. Isn’t it?
data class UserFeedback(val name: String, val emailId: String, val comments: String)
2.1. Kotlin data class
We mark the data class using the keyword data:
data class UserFeedback(val name: String, val emailId: String, val comments: String)
The compiler auto-generates the below members from all properties declared in the primary constructor:
equals()
andhashCode()
toString()
– format"UserFeedback(name=John, emailId=john@tedblob.com, comments=Can you improve this part)"
componentN()
- copy
- getters and setters
The generation of data class members adheres to the below rules regarding the members’ inheritance:
- If there are explicit implementations of
equals()
,hashCode()
, ortoString()
in the data class body orfinal
implementations in a superclass, then the compiler won’t create the functions and uses the existing implementations. - You can’t provide explicit implementations for the componentN() and copy() functions. If you try to override, then it throws a conflicting overloads error.
data class UserFeedback constructor(val name: String, val emailId: String, val comments: String) { fun copy(name: String = this.name, emailId: String = this.emailId, comments: String = this.comments) = UserFeedback(name, emailId, comments) }
2.2. Constructor Kotlin data class
The compiler generates the utility methods based on the declaration of the primary constructor. For the data class to work as expected, your data classes have to fulfill the below requirements:
- The primary constructor with at least one parameter.
- All primary constructor parameters should be
val
orvar
. - Data classes cannot be abstract, open, sealed, or inner.
2.3. Kotlin Data class toString
During development, it is very common to display the data in the logs for debugging and testing.
If you want to display your feedback data in logs, then you would create toString method in Java. As mentioned prior, Kotlin auto-generates the toString method in the format UserFeedback(name=Siv, emailId=siv@tedblob.com, comments=Can you check this)
fun main() { val userFeedback = UserFeedback("Siv", "siv@tedblob.com", "Can you check this") System.out.println(userFeedback) } data class UserFeedback(val name: String, val emailId: String, val comments: String)
3. Conclusion
In this article, we have learned the Kotlin data class and its utility method toString. See our Kotlin articles to understand other Kotlin topics.
You can find code samples in our GitHub repository.