1. Overview
The Kotlin language introduces the concept of Data Classes, which represent simple classes used as data containers and do not encapsulate any additional logic. Simply put, Kotlin’s solution enables us to avoid writing a lot of boilerplate code.
In this quick article, we’ll take a look at Data Classes in Kotlin and compare them with their Java counterparts.
2. Kotlin Setup
To get started setting up the Kotlin project, check our introduction to the Kotlin Language tutorial.
3. Data Classes in Java
If we wanted to create a Movie entry in Java, we’d need to write a lot of boilerplate code:
public class Movie { private String name; private String studio; private float rating; public Movie(String name, String studio, float rating) { this.name = name; this.studio = studio; this.rating = rating; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getStudio() { return studio; } public void setStudio(String studio) { this.studio = studio; } public float getRating() { return rating; } public void setRating(float rating) { this.rating = rating; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((name == null) ? 0 : name.hashCode()); result = prime * result + Float.floatToIntBits(rating); result = prime * result + ((studio == null) ? 0 : studio.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; Movie other = (Movie) obj; if (name == null) { if (other.name != null) return false; } else if (!name.equals(other.name)) return false; if (Float.floatToIntBits(rating) != Float.floatToIntBits(other.rating)) return false; if (studio == null) { if (other.studio != null) return false; } else if (!studio.equals(other.studio)) return false; return true; } @Override public String toString() { return "Movie [name=" + name + ", studio=" + studio + ", rating=" + rating + "]"; } }
86 lines of code. That’s a lot to store only three fields in a simple class.
4. Kotlin Data Class
Now, we’ll create the same Movie class, with the same functionalities, using Kotlin:
data class Movie(var name: String, var studio: String, var rating: Float)
As we can see, that’s massively easier and cleaner. Constructor, toString(), equals(), hashCode(), and additional copy() and componentN() functions are generated automatically.
4.1. Usage
A data class is instantiated the same way as other classes:
val movie = Movie("Whiplash", "Sony Pictures", 8.5F)
Now, the properties and functions of are available:
println(movie.name) //Whiplash println(movie.studio) //Sony Pictures println(movie.rating) //8.5 movie.rating = 9F println(movie.toString()) //Movie(name=Whiplash, studio=Sony Pictures, rating=9.0)
4.2. Copy Function
The copy() function is created, in case that we need to copy an object altering some of its properties but keeping the rest unchanged.
val betterRating = movie.copy(rating = 9.5F) println(betterRating.toString()) // Movie(name=Whiplash, studio=Sony Pictures, rating=9.5)
Java doesn’t provide a clear, native way for copying/cloning objects. We could use the Clonable interface, SerializationUtils.clone() or a cloning constructor.
4.3. Destructuring Declarations
Destructuring Declarations allow us to treat objects properties as individual values. For each property in out data class, a componentN() is generated:
movie.component1() // name movie.component2() // studio movie.component3() // rating
We can also create multiple variables from the object or directly from a function – it’s important to remember about using brackets:
val(name, studio, rating) = movie fun getMovieInfo() = movie val(namef, studiof, ratingf) = getMovieInfo()
4.4. Data Class Requirements
In order to create a data class, we have to fulfill the following requirements:
- The primary constructor needs to have at least one parameter
- All primary constructor parameters need to be marked as val or var
- Data classes cannot be abstract, open, sealed or inner
- (before 1.1.) Data classes may only implement interfaces
Since 1.1, data classes may extend other classes.
If the generated class needs to have a parameterless constructor, default values for all properties have to be specified:
data class Movie(var name: String = "", var studio: String = "", var rating: Float = 0F)
5. Conclusion
We’ve seen Data Classes in Kotlin, their usage and requirements, the reduced amount of boilerplate code written, and comparisons with the same code in Java.
If you want to learn more about Kotlin, check articles such as Kotlin Java Interoperability and the already mentioned Introduction to the Kotlin Language.
The full implementation of these examples can be found in our GitHub project.