开发者

Using Java annotations with Java interface implementations in Scala

EDIT: This issue appears to have been resolved as of 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();
}

The library has methods that expect a user defined interface that contains one or more methods annotated with @Anno.

I'm exploring converting existing code from Java to Scala. The existing codebase contains an implementation of IFace:

public class Impl implements IFace<String> { }

And I'm trying to create a Scala class that is usable by the 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 appears to be rejecting the code because it doesn't believe that Impl extends IFace. Is this a limitation of Java/Scala interoperability, or do I need to specify my use of the Java annotation differently in Scala?

EDIT: The original Java version of Usage, which compiles, looks like:

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

I'm trying to find the correct 开发者_如何学运维syntax to say the same thing in Scala.


Example compiles after adding wildcard to Anno definition:

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

I can assume that compiler doesn't treat IFace like IFace[_] and doesn't believe that IFace[String] (and therefore Impl) extends IFace.


This is one of these borderline cases where Scala does not inter-operate well with Java. The problem is that a type declared as generics is latter used as a raw type:

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

The most commonly used solution in this case -- and I recommend you look up questions about raw type interaction with Scala, as there were other such cases here on Stack Overflow -- is to write a wrapper in Java.

I'm not sure this would be possible here, but you might try to extend Anno overriding value with a compatible type signature. Maybe narrow the return type to Class<? extends Impl>, or maybe just rewrite it to use generics in IFace as well.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜