- Kotlin data class
- 2. POJO class in Kotlin
- 2.1. Data class
- 2.2. Constructor Kotlin data class
- 2.2.1. Kotlin data class private constructor
- 2.3. Kotlin Data class toString
- 2.4. Kotlin data class equals and hashcode
- Data class Kotlin equals
- Kotlin compare data classes
- Kotlin data class hashcode
- 2.5 copy() function
- 3. Conclusion
- 6 thoughts on “Kotlin data class”
- toString
- Exceptions
- Exceptions
- Exceptions
- Exceptions
- Exceptions
- Exceptions
- Exceptions
- Exceptions
- Kotin – toString() – convert Kotlin Data Class Object to String
- 1. Default toString() method
- 2. Override toString() method
Kotlin data class
In this article, we will discuss the Kotlin data class. The primary purpose of this data class is to hold data and doesn’t provide any other functionality. Kotlin generates necessary utility functions for this class.
2. POJO class in Kotlin
You would have created classes to hold data and do nothing else. In Java, you call it POJO (Plain Old Java Object). You should have also written utility functions like getters, setters, toString, constructors, 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 for 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 wrote 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. 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() and hashCode()
- 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() , or toString() in the data class body or final implementations in a superclass, then 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 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) // throws error "Conflicting overloads: public final fun copy(name: String = . emailId: String = . comments: String = . ): UserFeedback defined in UserFeedback" >
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 or var .
- Data classes cannot be abstract, open, sealed, or inner.
2.2.1. Kotlin data class private constructor
What if you want your class constructor to be private and prevent other classes from instantiating your data class?
You can declare your data class private. But data class still exposes the constructor via copy function. Don’t worry if it makes little sense.
Let’s see an example to understand this. Suppose you want your data class to be a singleton. You can create a companion object and instantiate the instance internally within the data class to share it with other classes.
This looks fine. But there is an issue here. The compiler generates the copy function for your data class. Though your data class is private, the copy function still exposes your constructor.
In the below example, CriticalDefect has a private constructor and other classes can’t instantiate directly. But you can use the copy function to create a new instance. copiedInstance is a new instance created from the singleton instance.
fun main() < val defect = CriticalDefect.getSingletonInstance(); val copiedInstance = defect.copy(defectSeverity = "low") System.out.println("defect : " + defect) // returns defect : CriticalDefect(defectSeverity=high) System.out.println("copiedInstance : " + copiedInstance) // returns copiedInstance : CriticalDefect(defectSeverity=low) >data class CriticalDefect private constructor(val defectSeverity: String) < companion object < const val HIGH = "high" private var criticalDefect: CriticalDefect? = null fun getSingletonInstance() : CriticalDefect < if (criticalDefect == null) < criticalDefect = CriticalDefect(HIGH) >return criticalDefect as CriticalDefect > > >
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)
// file name: tedblob.kt 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)
2.4. Kotlin data class equals and hashcode
Let’s see the equals and hashcode functions generated by the data class.
Data class Kotlin equals
There are chances to have duplicate feedback entries. To check the objects are equal, You generate equals method in Java. But compiler auto-generates the equals function for the data class.
Kotlin compare data classes
You can compare the data classes easily as below.
fun main() < val userFeedback = UserFeedback("Siv", "siv@tedblob.com", "Can you check this") val duplicate = UserFeedback("Siva", "siv@tedblob.com", "Can you check this") System.out.println(userFeedback.equals(duplicate)) >data class UserFeedback constructor(val name: String, val emailId: String, val comments: String)
Kotlin data class hashcode
The hashcode function returns a numeric representation of an object’s contents. The value received from hashCode() is used as the bucket number for storing elements of the Hashset and HashMap. This bucket number is the address of the element inside the Hashset and HashMap.
When you invoke contains() function it will take the hash code of the element, then look for the bucket where the hash code points to.
Whenever you invoke the hash function on the same object more than once, it would consistently return the same integer. If two objects are equal according to the equals method, then calling hashCode function from those two objects always produce the same integer result.
fun main() < val userFeedback = UserFeedback("Siv", "siv@tedblob.com", "Can you check this") val duplicate = UserFeedback("Siv", "siv@tedblob.com", "Can you check this") System.out.println(userFeedback.hashCode() == duplicate.hashCode()) // returns true >data class UserFeedback constructor(val name: String, val emailId: String, val comments: String)
2.5 copy() function
Sometimes you want to create a new object from an existing object while altering only a few properties and keeping the rest unchanged.
The implementation of the copy function for the UserFeedback class would be:
fun copy(name: String = this.name, emailId: String = this.emailId, comments: String = this.comments) = UserFeedback(name, emailId, comments)
You can use copy function in those scenarios. The below code creates a copy from userFeedback while changing the name attribute.
// file name: tedblob.kt fun main() < val userFeedback = UserFeedback("Siv", "siv@tedblob.com", "Can you check this") val copyFeedback = userFeedback.copy("Praj") System.out.println(userFeedback) // UserFeedback(name=Siv, emailId=siv@tedblob.com, comments=Can you check this) System.out.println(copyFeedback) // UserFeedback(name=Praj, emailId=siv@tedblob.com, comments=Can you check this) >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 methods. See our Kotlin articles to understand other Kotlin topics.
6 thoughts on “Kotlin data class”
- Pingback: Destructuring declarations in Kotlin to destructure an object — TedBlob
- Pingback: Introduction to Kotlin Serialization: kotlinx serialization tool — TedBlob
- Pingback: Kotlin component functions — TedBlob
- Pingback: Kotlin array destructuring — TedBlob
- Pingback: Create Kotlin class from json — TedBlob
- Pingback: Java: Automatic Equals() And HashCode() — Programming Questions And Solutions Blog
toString
Returns a string representation of this Byte value in the specified radix.
Exceptions
IllegalArgumentException — when radix is not a valid radix for number to string conversion.
Returns a string representation of this Short value in the specified radix.
Exceptions
IllegalArgumentException — when radix is not a valid radix for number to string conversion.
Returns a string representation of this Int value in the specified radix.
Exceptions
IllegalArgumentException — when radix is not a valid radix for number to string conversion.
Returns a string representation of this Long value in the specified radix.
Exceptions
IllegalArgumentException — when radix is not a valid radix for number to string conversion.
Returns a string representation of this Byte value in the specified radix.
Exceptions
IllegalArgumentException — when radix is not a valid radix for number to string conversion.
Returns a string representation of this Short value in the specified radix.
Exceptions
IllegalArgumentException — when radix is not a valid radix for number to string conversion.
Returns a string representation of this Int value in the specified radix.
Exceptions
IllegalArgumentException — when radix is not a valid radix for number to string conversion.
Returns a string representation of this Long value in the specified radix.
Exceptions
IllegalArgumentException — when radix is not a valid radix for number to string conversion.
Kotin – toString() – convert Kotlin Data Class Object to String
In the post, JavaSampleApproach will guide how to convert Kotlin object to String by toString() method.
1. Default toString() method
To convert Kotlin Object to Kotlin String, we can use toString() method.
package com.javasampleapproach.kotlin.tostring data class Address( val street: String, val postcode: String ) data class Person(val id: Long, val firstName: String, val lastName: String, val age: Int, val address: Address ) fun main(args : Array) < val address = Address("NANTERRE CT", "77471") val address2Str = address.toString() println(address2Str) /* ->Address(street=NANTERRE CT, postcode=77471) */ val person = Person(1, "Jack", "Davis", 25, address) val person2Str = person.toString() println(person2Str) /* -> Person(id=1, firstName=Jack, lastName=Davis, age=25, address=Address(street=NANTERRE CT, postcode=77471)) */ >
2. Override toString() method
When we want to modify the output of default toString() method, we can override the implementation of toString() .
package com.javasampleapproach.kotlin.override.tostring data class Address( val street: String, val postcode: String )< override fun toString(): String< val address2Str = ", postcode = $>" return address2Str > > data class Person(val id: Long, val firstName: String, val lastName: String, val age: Int, val address: Address )< override fun toString(): String< val person2Str = ", age = $, address = $>" return person2Str > > fun main(args : Array) < val address = Address("NANTERRE CT", "77471") val address2Str = address.toString() println(address2Str) /* -> */ val person = Person(1, "Jack", "Davis", 25, address) val person2Str = person.toString() println(person2Str) /* ->*/ >