2

Here are my Kotlin (Version 1.3.61) + Java(1.8.0_201) code that failed to compile:

Maven:

<dependency> <groupId>com.google.code.findbugs</groupId> <artifactId>jsr305</artifactId> <version>2.0.1</version> </dependency> 

Test.Kt:

fun main(args: Array<String>) { Point().setX(1) } 

Point.java:

import javax.annotation.Nonnull; public class Point { public void setX(int x) { } public void setX(@Nonnull Integer x) { } } 

Failed to compile due to the following error:

Error:(2, 13) Kotlin: Overload resolution ambiguity: public open fun setX(@Nonnull x: Int): Unit defined in Point public open fun setX(x: Int): Unit defined in Point 

If I removed the @NonNull annotation in the second setX function, then this demo could compile. I thought Java annotation was only extra metadata and would not affect the code itself, so I had no idea why the ambiguity arose here.

Also, I run javap -s Point.class and found out that they had same output:

public void setX(java.lang.Integer); descriptor: (Ljava/lang/Integer;)V 

Can someone help to explain what is going on here? Thanks in advance.

2
  • 2
    Maybe take a step back and explain why in the first place you even have those two methods. I wouldn't see how having both of these would make a difference for the caller Commented Jan 8, 2020 at 7:46
  • A similar code was generated from Avro in my project. Though they are not supposed to be called directly, they are public. Therefore I had this question. @LinosaysReinstateMonica Commented Jan 8, 2020 at 17:32

1 Answer 1

4

From kotlin in action

sometimes Java code contains information about nullability, expressed using annotations. When this information is present in the code, Kotlin uses it. Thus @Nullable String in Java is seen as String? by Kotlin, and @NotNull String is just String. The interesting question is what happens when the annotations aren’t present. In that case, the Java type becomes a platform type in Kotlin.

When you use Java declarations from Kotlin, Java primitive types become non-null types (not platform types), because they can’t hold null values.

in your case first method has a java primitve type as parameter and because primitives can't be null kotlin translates it to

setX(x: Int) 

and since second method contains @Nonnull annotation, kotlin uses this information and hence it translates the method to

setX(x: Int) 

so as you can see for kotlin they are two different methods with exact same signature, hence the ambiguity.

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.