Using Java annotations with Java interface implementations in Scala

EDIT: This issue seems to have been resolved with Scala 2.9.1

Given the following existing Java library (simplified):

public interface IFace<T> {} @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.METHOD}) public @interface Anno { Class<? extends IFace> value(); } 

There are methods in the library that expect a user-defined interface that contains one or more methods annotated with @Anno .

I am learning to convert existing code from Java to Scala. The existing code base contains an implementation of IFace :

 public class Impl implements IFace<String> { } 

And I'm trying to create a Scala class that can be used in a library:

 trait Usage { @Anno(classOf[Impl]) def aMethod(): String } 

The Scala compiler rejects this:

 $ scalac -explaintypes Usage.scala Usage.scala:5: error: type mismatch; found : java.lang.Class[Impl](classOf[Impl]) required: java.lang.Class[_ <: IFace] @Anno(classOf[Impl]) ^ java.lang.Class[Impl](classOf[Impl]) <: java.lang.Class[_ <: IFace]? java.lang.Class[Impl](classOf[Impl]) <: java.lang.Class[?0?0]? java.lang.Class[Impl] <: java.lang.Class[?0?0]? ?0?0 <: Impl? true Impl <: ?0?0? true true true Nothing <: Impl? <notype> <: Impl? false true Impl <: IFace? false java.lang.Class[Impl] <: java.lang.Class[_ <: IFace]? java.lang.Class[Impl] <: java.lang.Class[?0?0]? ?0?0 <: Impl? true Impl <: ?0?0? true true Nothing <: Impl? <notype> <: Impl? false true Impl <: IFace? false false false one error found 

It seems that it rejects the code because it does not consider Impl extends IFace . Is this a Java / Scala compatibility limitation, or do I need to specify my use of Java annotations differently in Scala?

EDIT: The original version of Java Usage that compiles looks like this:

 public interface Usage { @Anno(Impl.class) String aMethod(); } 

I am trying to find the correct syntax to say the same thing in Scala.

+4
source share
2 answers

This is one of these borderline cases where Scala does not interact with Java. The problem is that the type declared as generics is used by the latter as the raw type:

 public interface IFace<T> {} // ... Class<? extends IFace> value(); 

The most commonly used solution in this case - and I recommend that you look at questions about the interaction of the raw type with Scala, since there were other similar cases in Qaru - is to write a shell in Java.

I'm not sure if this is possible here, but you can try extending Anno overriding value to a compatible type signature. Maybe narrow the return type to Class<? extends Impl> Class<? extends Impl> or maybe just rewrite it to use generics in IFace .

+1
source

Compilation example after adding a template to Anno :

 Class<? extends IFace<?>> value(); 

I can assume that the compiler does not treat IFace as IFace[_] and does not consider IFace[String] (and therefore Impl ) to extend IFace .

+2
source

All Articles