1. Overview

In this tutorial, we’ll explore the Kotlin error, “Accidental override: The following declarations have the same JVM signature”. Then, we’ll explore how to fix this problem in our code.

2. Why Do Declarations Have the Same JVM Signature?

Kotlin and Java are interoperable languages. Kotlin compiles to JVM-compliant bytecode, meaning that it generates the same bytecode as Java, which allows these languages to work together.

When the Kotlin compiler runs, the Kotlin code will be transformed into Java bytecode. When this bytecode is generated, some instructions and names are converted to others to ensure compatibility with the Java programming language. The simplest example of this is using a Java POJO from Kotlin: If we have a variable in Kotlin, var x, it will have getters and setters generated for Java compatibility.

Let’s create an example of this JVM signature problem with a mixed class hierarchy. The easiest way to achieve this is by creating competing signatures in Java and Kotlin:

//Java
public interface Animal {
    default String getSound() { return ""; }
}

//Kotlin
class Cat : Animal {
    val sound: String = "Meow"
}

When we try to compile our code, we’ll see the error:

Kotlin: Accidental override: The following declarations have the same JVM signature (getSound()Ljava/lang/String;):
fun `<get-sound>`(): String defined in com.baeldung.accidental_override.Cat
fun getSound(): String? defined in com.baeldung.accidental_override.Cat

This happened because our sound property inside Cat has the getSound() getter generated, which clashes with the same method in Animal and thus can’t compile.

3. Solving the Error

There are several ways to get past this error, which we will explore now.

3.1. Removing the Offending Property

The simplest way to solve this is by removing the offending property from our object. It’s usually not the solution we want, but if the property had that signature by accident, removing it is a quick fix with low effort:

class Cat : Animal {
//    val sound: String = "Meow"
}

Instead of simply removing the variable, we can rename it to something else instead:

class Cat : Animal {
    val myCatSound: String = "Meow"
}

If we intended to override a property, we can properly override it to remove the error:

class Cat : Animal {
    override fun getSound(): String {
        return "Meow"
    }
}

3.2. Using @JvmName

A more complex way to solve this issue is adding the @JvmName annotation to our property. This annotation tells the Kotlin compiler what it must use as a name in the bytecode to avoid the name clash altogether. Applying it to our sound property is easy:

class Cat : Animal {
    @get:JvmName("cat_sound")
    val sound: String = "Meow"
}

After applying the annotation, instead of getSound(), the generated getter function will have cat_sound() as its signature because we are only renaming the generated getter with the “get:” prefix of the annotation.

4. Conclusion

In this article, we learned how to avoid the Kotlin error “Accidental override: The following declarations have the same JVM signature” by either refactoring our class or specifying more information to the Kotlin compiler. As always, the example code in this article can be found over on GitHub.

Comments are open for 30 days after publishing a post. For any issues past this date, use the Contact form on the site.