//Callbacks.java
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Callbacks {
Callback[] value();
}
And I am using them in Java 8 just fine.
//Demo.java
@Callback(Fizz.java)
@Callback(Buzz.java)
public class Demo {
//......
}
But when I convert that class into a Kotlin class
//Demo.kt
@Callback(Fizz::class)
@Callback(Buzz::class)
class Demo {
//......
}
I get the following error
Only annotations with SOURCE retention can be repeated on JVM version before 1.8
I’m not sure if this is a Kotlin/Java 8 incompatibility or I just have my project set up wrong. I should also note that the kotlin code above works fine if I only have one @Callback.
Thanks
Basically, the Kotlin compiler for now targets the jdk 1.6 class file format. This means that, on Java, it cannot write multiple annotations to the class file. While conceptually Kotlin supports multiple annotations, until there is proper 1.8 targeting (scheduled for 1.1), it cannot do so because of the output restrictions. Source level annotations are not written to the class file so there is no issue for that.
So, wait until 1.1, use a hack where you use the annotations in Java, or if possible, use a container annotation that contains a list of callbacks (the way this was done before 1.8).
Hi,I’m using Kotlin maven plugin version 1.1.1 and I’ve configured jvmTarget param with 1.8, but still have the same error
would you please give some advices?
We are hitting this at the moment. It’d be great if Kotlin 1.3 could focus on catching up with Java 8 because right now there are still a bunch of tasks where Java is actually better or easier to use than Kotlin - none of them are large, but it seems a shame whenever Java is ahead of Kotlin.
FWIW, this issue is serious enough for me to take my project back to Java…I have to interface with a Java framework that makes extensive use of Annotations. The discovery that Kotlin is essentially Java 6 in this respect makes me sad
I found that this workaround is not universal. It works fin if annotations themselves are defined in java, but does not work if the code is pure kotlin. This is caused by the fact that kotlin hide java parametric Repeatable annotations with its own annotation. Therefore grouping annotation could not be found by java reflections.
As a temporary fix (while there is no repeatable annotation support) I would like to propose to return Java Repeatable(Class) annotation or to make some way of applying it.
For now, it is really inconvenient, I will have to move annotation declarations back to java and I wanted to completely avoid java code in some parts of the project.
The situation is probably not as bad to have a need for going back to Java (see @merrill77), just use the right annotation. Expanding on OP’s example via pure Kotlin declarations:
@Suppress("DEPRECATED_JAVA_ANNOTATION") // suppress deprecation for java.lang.annotation.Repeatable
@java.lang.annotation.Repeatable(Callbacks::class) // define container for compatibility
// standard annotation definition follows:
@Retention(AnnotationRetention.RUNTIME)
@Target(AnnotationTarget.CLASS)
@Repeatable // use Kotlin annotation as well just to be safe (for tools and stuff)
annotation class Callback(val value: KClass<*>)
/** Container annotation for repeating without repeatable support */
@Retention(AnnotationRetention.RUNTIME)
@Target(AnnotationTarget.CLASS)
annotation class Callbacks(vararg val value: Callback)
@Callback(C1::class)
@Callback(C2::class) // errors
class DoesNotSupportRepeated
@Callbacks(
Callback(C1::class), // don't forget the comma!
Callback(C2::class) // works
)
class SupportsRepeated