Designing APIs for Java only

When designing APIs that require Java interoperability, sometimes I create classes that are specifically targeting Java but should not be used on Kotlin. However, new developers (mostly coming from a Java background) may tend to use Java-friendly APIs instead.

One naive example is to provide a DSL syntax for Kotlin users but provide a fluent Builder for Java users of the SDK. The latter works with Kotlin but it is not designed to be used with Kotlin due to the already provided DSL syntax. For that reason, I want to communicate:

  • Java users should use the Builder API only.
  • Kotlin users should use the DSL API only.

I’m aware we can flag code designed only to Java with @JvmSynthetic but is there a way to do the opposite? One way I see is to create a @OptIn contract targeting Java interoperability but I’m not sure if that is the recommended way.

Thank you!

I think you meant the opposite? @JvmSynthetic makes the code Kotlin-only.

For the Java-only code you can simply use internal visibility. It is public in Java. This is more like a workaround than a real solution, but the same can be said about @JvmSynthetic.

3 Likes

You could also do @Deprecated(level = DeprecationLevel.HIDDEN) which hides it completely on the kotlin side

1 Like

@broot no, my intention is to not have it available in Kotlin. For example:

// to be used in Java. 
fun <T> foo(classRef: KClass<T>) = TODO()

// to be used in Kotlin. 
inline fun <reified T> foo() = TODO()

Today, a Kotlin developer can use any of those and that is correct. What I wonder is: how can I communicate better which one should be used by Kotlin developers. That is specially valuable with less experience engineers.

@kyay10 it is a nice idea, but that should create unnecessary warnings in the Java codebase, which isn’t ideal…

Yes, and I provided you exactly that, didn’t I?

1 Like

@broot as a workaround, yes. My answer above was mostly to be clear about this part of your answer:

I think you meant the opposite?