Question
Kotlin Interfaces and SAM Conversion: Why "Interface Does Not Have Constructors" Happens
Question
I am converting Java code to Kotlin and I am confused about how to create an instance of an interface.
In Java, I have this interface:
public interface MyInterface {
void onLocationMeasured(Location location);
}
In Kotlin, I can create an instance of that Java interface like this:
val myObj = MyInterface {
Log.d("...", "...")
}
This works.
But after converting the interface itself to Kotlin:
interface MyInterface {
fun onLocationMeasured(location: Location)
}
I now get the error:
Interface MyInterface does not have constructors
when I try to instantiate it in the same style.
It seems like only the syntax changed. Why does this happen in Kotlin, and what is the correct way to create an instance of a Kotlin-defined interface?
Short Answer
By the end of this page, you will understand why Kotlin lets you create Java single-method interfaces with lambda syntax, why the same syntax does not automatically work for Kotlin-defined interfaces, and how to correctly instantiate Kotlin interfaces using object expressions or fun interface when appropriate.
Concept
The core concept behind this question is SAM conversion.
SAM stands for Single Abstract Method. A SAM type is an interface that has exactly one abstract method. In Java, interfaces like this are often used as callbacks:
public interface MyInterface {
void onLocationMeasured(Location location);
}
Because there is only one method to implement, Kotlin can often let you replace the full anonymous class with a lambda.
Why the Java version works
When MyInterface is defined in Java and has one abstract method, Kotlin recognizes it as a Java SAM interface. That means this is allowed:
val myObj = MyInterface {
Log.d("TAG", "measured")
}
Kotlin converts the lambda into an object that implements the interface.
Why the Kotlin version fails
When you rewrite the interface in Kotlin as:
interface MyInterface {
fun onLocationMeasured(location: Location)
}
it is now just a normal Kotlin interface. A normal interface is and . So Kotlin does not treat as "call a constructor" or "build an implementation" unless the interface is specifically declared as a functional interface.
Mental Model
Think of a normal Kotlin interface as a contract sheet.
It says:
- "Any class using me must provide these methods"
But it does not come with a built-in factory or constructor.
So this does not make sense:
MyInterface { ... }
because you are writing something that looks like calling a constructor, but an interface is not constructible.
Now think of a fun interface as a special one-button adapter.
Because it has only one job, Kotlin can say:
- "If you give me a lambda, I know how to turn that into an implementation."
So:
val myObj = MyInterface { location ->
println(location)
}
works only when Kotlin knows the interface is a functional interface.
Simple analogy
interface= a job descriptionobject : Interface { ... }= hiring a worker and explicitly telling them how to do the jobfun interface+ lambda = using a quick one-task freelancer form because there is only one task to define
Syntax and Examples
1. Normal Kotlin interface: use an object expression
interface MyInterface {
fun onLocationMeasured(location: Location)
}
val myObj = object : MyInterface {
override fun onLocationMeasured(location: Location) {
Log.d("TAG", "Location measured: $location")
}
}
This is the correct way to create an instance of a regular Kotlin interface.
Why it works
object : MyInterfacecreates an anonymous object- That object implements
MyInterface - You must override all required abstract methods
2. Kotlin functional interface: use fun interface
fun interface MyInterface {
fun onLocationMeasured(location: Location)
}
myObj = MyInterface { location ->
Log.d(, )
}
Step by Step Execution
Consider this Kotlin code:
fun interface MyInterface {
fun onLocationMeasured(location: String)
}
fun main() {
val myObj = MyInterface { location ->
println("Measured: $location")
}
myObj.onLocationMeasured("Paris")
}
Step by step
1. Kotlin sees fun interface
fun interface MyInterface {
This tells the compiler:
- this interface has one abstract method
- it can be instantiated from a lambda
2. Kotlin reads the lambda assignment
val myObj = MyInterface { location ->
println("Measured: $location")
}
Kotlin converts this lambda into an object that implements MyInterface.
Conceptually, it is similar to:
Real World Use Cases
Callback APIs
Interfaces are commonly used to receive events from another part of the program.
Examples:
- location updates
- button click handlers
- download completion events
- sensor readings
fun interface OnDownloadComplete {
fun onDone(fileName: String)
}
Android listeners
In Android, many Java-based APIs use listener interfaces. Kotlin often lets you pass lambdas for these because they are Java SAM interfaces.
button.setOnClickListener {
Log.d("TAG", "Clicked")
}
Custom Kotlin APIs
If you are designing your own callback API in Kotlin and want callers to use lambdas, fun interface is often a good choice.
fun interface OnUserLoaded {
fun onLoaded(name: String)
}
Multiple related callbacks
If your API needs several methods, a regular interface is more appropriate.
Real Codebase Usage
In real projects, developers choose between lambdas and object expressions based on API design.
Pattern 1: Simple callback with fun interface
Use this when there is only one action to perform.
fun interface OnSave {
fun onSave(fileName: String)
}
This keeps call sites clean:
saveDocument(OnSave { fileName ->
println("Saved $fileName")
})
Pattern 2: Object expression for richer behavior
If the interface has multiple methods or stateful logic, use an object expression.
interface AuthListener {
fun onSuccess(userId: String)
fun onError(message: String)
}
val listener = object : AuthListener {
override fun onSuccess {
println()
}
{
println()
}
}
Common Mistakes
1. Treating a normal interface like a constructor
Broken code:
interface MyInterface {
fun onLocationMeasured(location: String)
}
val obj = MyInterface {
println(it)
}
Why it fails:
MyInterfaceis not a class- it has no constructor
- normal Kotlin interfaces do not support lambda instantiation
Fix:
val obj = object : MyInterface {
override fun onLocationMeasured(location: String) {
println(location)
}
}
2. Forgetting to use fun interface
Broken code:
interface OnDone {
fun complete()
}
val callback = OnDone {
println("done")
}
Comparisons
| Concept | Kotlin syntax | Lambda allowed? | Best use case |
|---|---|---|---|
| Java single-method interface | interface in Java | Yes, from Kotlin | Existing Java callback APIs |
| Kotlin normal interface | interface MyInterface | No | Multiple methods or richer contracts |
| Kotlin functional interface | fun interface MyInterface | Yes | Kotlin callback APIs with one abstract method |
| Anonymous object | object : MyInterface { ... } | Not a lambda, but always works for interfaces | Custom one-off implementations |
interface vs
Cheat Sheet
Quick rules
- A normal Kotlin
interfacehas no constructor. MyInterface { ... }only works for SAM-compatible interfaces.- Java single-method interfaces are usually SAM-compatible in Kotlin.
- Kotlin-defined interfaces need
fun interfacefor lambda instantiation. - If the interface has multiple abstract methods, use
object : InterfaceName { ... }.
Normal interface
interface MyInterface {
fun onLocationMeasured(location: String)
}
val obj = object : MyInterface {
override fun onLocationMeasured(location: String) {
println(location)
}
}
Functional interface
fun interface MyInterface {
fun onLocationMeasured(location: String)
}
val obj = MyInterface { location ->
println(location)
}
FAQ
Why does Kotlin say an interface does not have constructors?
Because an interface is not a class you can instantiate directly. MyInterface { ... } only works when Kotlin supports SAM conversion for that interface.
Why did the Java interface work but the Kotlin one did not?
Kotlin supports SAM conversion for Java single-method interfaces. A regular Kotlin interface does not automatically get the same treatment.
How do I instantiate a Kotlin interface correctly?
Use an object expression:
val obj = object : MyInterface {
override fun onLocationMeasured(location: Location) {
// code
}
}
When should I use fun interface?
Use it when your Kotlin interface has exactly one abstract method and you want callers to be able to pass a lambda.
Can a fun interface have more than one method?
It can only have one abstract method. Additional non-abstract members may be allowed, but the functional part must remain exactly one abstract method.
Is a lambda the same as an object expression?
Not exactly. A lambda is shorthand for implementing a functional interface or function type. An object expression creates an anonymous object explicitly.
Should I use a function type instead of a ?
Mini Project
Description
Build a small location event handler that demonstrates both ways of implementing interface-based callbacks in Kotlin: using an object expression for a normal interface and using a lambda for a fun interface. This mirrors real app code where one component reports events and another reacts to them.
Goal
Create a simple program that sends location updates to listeners using both a regular Kotlin interface and a functional Kotlin interface.
Requirements
- Define one regular Kotlin interface with a single method.
- Define one
fun interfacewith a single method. - Create an implementation of the regular interface using an object expression.
- Create an implementation of the functional interface using a lambda.
- Call both listeners and print their output.
Keep learning
Related questions
Accessing Kotlin Extension Functions from Java
Learn how Kotlin extension functions are compiled and how to call them correctly from Java with clear examples and common pitfalls.
Allow HTTP and HTTPS in Android 9 Pie with Network Security Configuration
Learn how Android 9 Pie handles cleartext HTTP traffic and how to allow HTTP and HTTPS safely using network security config.
Android AlarmManager Example: Scheduling Tasks with AlarmManager
Learn how to use Android AlarmManager to schedule tasks, set alarms, and handle broadcasts with a simple beginner example.