1. Overview
In this tutorial, we’ll take a thorough look at constructors in Kotlin.
Let’s start with a quick recap of the concept: we use constructors to create objects. These look like method declarations, but always have the same name as the class and they don’t return anything.
For the setup of a Kotlin project, have a look at our introductory tutorial.
In Kotlin, a class can have a primary constructor and one or more additional secondary constructors.
In the next sections, we’ll go over each type and associated concepts.
2. Primary Constructor
The first way to create an object in Kotlin is by using a primary constructor.
This is a part of the class header. Parameters might also be class fields, which we place after the class declaration.
Let’s take a look at a basic class declaration, with two properties and a primary constructor:
class Person constructor(val name: String, val age: Int? = null)
In this example, we’ve declared properties through the val keyword. This behaves the same way as regular variables, with the mention that val properties are read-only (Java final keyword counterpart).
If we want to change the reference later, we should use the var keyword instead. However, we can’t omit the type of field in the primary constructor, as this must be explicit.
In some cases, we can omit the constructor keyword. This is only mandatory in two cases: when we use annotations, like @Autowired or access modifiers, like private or protected.
Also, we can use Kotlin default parameters in the constructors.
Next, let’s see how we can use our primary constructor:
val person = Person("John")
val personWithAge = Person("Mark", 22)
We can see that a class name is a constructor invocation. There’s no need to use the new keyword.
For reference, let’s also have a look at the Java equivalent of a constructor declaration:
class PersonJava {
final String name;
final Integer age;
public PersonJava(String name) {
this.name = name;
this.age = null;
}
public PersonJava(String name, Integer age) {
this.name = name;
this.age = age;
}
}
As you can see, Java would need much more code to achieve the same result.
2.1. Primary Constructors on the JVM
Please note that the compiler will generate an additional constructor without parameters on the JVM. For this purpose, it’ll instantiate an object with default values.
This way, Kotlin can work well with such libraries as Jackson or JPA, which use the no-args constructor to create class instances:
class Person(val name: String = "")
3. Initializing Properties from Constructor Parameters
Property initializers from the class body can use the primary constructor parameters.
Let’s transform name to the upperCaseName property:
class Person(val name: String, val age: Int? = null) {
val upperCaseName: String = name.toUpperCase()
}
We can see the output in the console by adding the second init block:
init {
println("Upper case name is $upperCaseName")
}
4. Initializer Blocks
We can’t put any code in the primary constructor.
However, we sometimes have to execute some initialization code. A good place for it is an initializer block, which is prefixed with the init keyword.
The initializer block is called after the primary constructor.** We can also access class fields in this place.
A class can have one or more init blocks.
Let’s append the initializer block to our Person class:
init {
println("Hello, I'm $name")
if (surname.isEmpty()) {
throw IllegalArgumentException("Surname cannot be empty!")
}
}
Next, when we create a Person class object, we’ll see in the console:
Hello, I'm John
We would throw IllegalArgumentException for the empty surname.
When we have many init blocks, they will be executed in the same order as they appear in the class body.
5. Secondary Constructor
In a Kotlin class, we can also declare one or more secondary constructors*.* Secondary constructors are prefixed with the constructor keyword:
class Car {
val id: String
val type: String
constructor(id: String, type: String) {
this.id = id
this.type = type
}
}
And the basic usage:
fun main(args: Array<String>) {
val car = Car("1", "sport")
val suvCar = Car("2", "suvCar")
}
Each secondary constructor has to delegate to the primary constructor.** We’ll do this by this keyword.
Let’s move our properties to the primary constructor and modify the secondary constructor:
class Car(val id: String, val type: String) {
constructor(id: String): this(id, "unknown")
}
6. Constructors and Inheritance
We can use a primary constructor of the superclass.
Note that all classes in Kotlin are final by default. This means we’ll need to add the open keyword so that we can inherit from our Person class.
Let’s add an Employee class that inherits from the Person class. They are both using primary constructors:
class Employee(name: String, val salary: Int): Person(name)
By doing this, we pass a name to the primary constructor of Person class. Additionally, we add a new field called salary in the Employee class.
7. Conclusion
In this quick article, we discussed various ways of creating constructors in the Kotlin language. We can instantiate our fields in many different ways, according to our wishes.
The implementation of all our examples can be found in the Github project.
For more information about Kotlin features itself, please have a look at our introduction to Kotlin.