How to overcome “same JVM signature” error when im

2020-02-20 06:21发布

问题:

With the code below, I am getting the following error in IntelliJ IDEA 13.1.6 and Kotlin plugin 0.11.91.AndroidStudio.3:

Platform declaration clash: The following declarations have the same JVM signature (getName()Ljava/lang/String;):
  • public open fun getName(): kotlin.String?
  • internal final fun <get-name>(): kotlin.String?

Java class, JavaInterface.java:

public interface JavaInterface {
  public String getName();
}

Kotlin class, KotlinClass.kt

public class KotlinClass(val name: String?) : JavaInterface

I've tried overriding the 'getter' method by adding override fun getName(): String? = name, but that produces the same error.

I can see one workaround by doing this instead:

public class KotlinClass(val namePrivate: String?) : JavaInterface {
  override fun getName(): String? = namePrivate
}

But in my real-world case I have a number of properties to implement and need setters too. Doing this for each property doesn't seem very Kotlin-ish. What am I missing?

回答1:

Making that variable private solves the problem.

public class KotlinClass(private val name: String?) : JavaInterface



回答2:

Another work-around is to declare the properties in an abstract Kotlin class, then write a small java class that extends KotlinClass and implements JavaInterface.

// JavaInterface.java
public interface JavaInterface {
    int getFoo();
    void setFoo(int value);
}

// KotlinClass.kt
abstract class KotlinClass(open var foo : Int = 0) {
}

// JavaAdapter.java
class JavaAdapter extends KotlinClass implements JavaInterface {
    // all code in KotlinClass, but can't implement JavaInterface there
    // because kotlin properties cannot override java methods.
}


回答3:

We have found that to use the same names without clashing, the ctor args must be private AND you must still override the interfaces methods. You don't need any additional backing fields. Also, your expression body assignment will not recurse, so you can safely use that syntax.

Java Interface

interface IUser {
    String getUserScope();
    String getUserId();
}

Kotlin Class

class SampleUser(private val userScope: String, private val userId: String) : IUser {
    override fun getUserId() = userId
    override fun getUserScope() = userScope
}


回答4:

You could use @JvmField for instructs the compiler not generate getter/setter, and you can implement your setters and getters. With this your code work well in Java (as attribute getter/setter) and Kotlin as property

Example: JAVA:

public interface Identifiable<ID extends Serializable> 
{
   ID getId();
} 

KOTLIN:

class IdentifiableImpl(@JvmField var id: String) :Identifiable<String> 
{
   override fun getId(): String 
   {
       TODO("not implemented")
   }
}


回答5:

If you have direct control over the interface then the best approach is to write the interface in Kotlin. You can then write your class

public class KotlinClass(override val name: String?) : KotlinInterface

and still reference it from any Java code using the same interface as before. This looks a lot neater than setting all the properties to private and overriding the get function. Obviously if you can't migrate the interface to Java because you don't own it then that seems to be the only solution.



回答6:

IMHO most readable combination is field + explicit interface implementation by the single-expression function (combination of @Renato Garcia's and @Steven Spungin's answers):

Java:

public inteface SomeInterface {
    String getFoo();
}

Kotlin:

class Implementation(@JvmField val foo: String) : SomeInterface {
    override fun getFoo() = foo
}


回答7:

public interface JavaInterface {
    public String getName();
}

public class KotlinClass(val namePrivate: String?) : JavaInterface {

private var name = namePrivate

    override fun getName(): String? {
        return name
    }
}


回答8:

Rename the variable to something else, or make it private if u dont want it to be public.



回答9:

The annotation feature of Kotlin named @JvmName will solve the duplication problem in Java and Kotlin when having the same signature.

fun function(p: String) {
   // ...
}

// Signature: function(Ljava/lang/String)

With the use of JvmName will be:

@JvmName("functionOfKotlin")
fun function(p: String) {
   // ...
}

// Signature: functionOfKotlin(Ljava/lang/String)


标签: kotlin