Description
In some cases, it is necessary to implement a Java annotation. For example, Guice provides an implementation of the javax.inject.Named
annotation:
Anything working with Guice may want to similarly provide implementations of other Qualifier
annotations, so that the value(s) associated with the annotation can be bound. So the named annotation might be implemented like this in Scala:
@SerialVersionUID(0)
private class NamedImpl(val value: String) extends Named with Serializable {
// This is specified in java.lang.Annotation.
override def hashCode: Int = (127 * "value".hashCode) ^ value.hashCode
override def equals(obj: Any) = obj match {
case named: Named => value == named.value
case _ => false
}
override def toString: String = s"@${classOf[Named].getName}(value=$value)"
def annotationType = classOf[Named]
}
However, there is a problem here, scalac considers the Named
annotation class to be an abstract class, not an interface, and so makes the annotation the super class, producing the following byte code:
$ javap NamedImpl.class
Compiled from "NamedImpl.scala"
public class NamedImpl extends javax.inject.Named implements scala.Serializable {
...
When this class is loaded, an IncompatibleClassChangeError
is raised, since the JVM considers an annotation to be an interface, not an abstract class.
The only way I can find to work around this is to implement the annotation in Java, not Scala.