2011-05-07 71 views
0

我在scala中使用Morphia时发现此问题。它通过反射来检查类的字段,并获取映射的必要类型信息。特征字段的泛型类型信息缺失?

但是,如果我使用traits并定义了一些集合字段,泛型类型信息将会丢失,这会导致Morphia无法获得足够的信息并抛出异常。

见我的代码:

trait HasTags { 
    @Reference 
    var tags: java.util.List[Tag] = new java.util.ArrayList[Tag]() // the generic type is Tag 
} 

class Question extends Entity with HasTags { 

} 

我编阶文件,并得到一些Java类文件。然后,我用java反编译器看到的Java字节代码的内容:

public class Question extends Entity implements HasTags { 
     @Reference 
     private java.util.List tags; 
} 

你可以看到这里没有Tag,所以吗啡会失败。我使用scala 2.8.1。有什么方法可以解决它吗?


UPDATE

@extempore说,也许javap不显示Tag信息。

但我使用了一个名为Java Decompiler而不是javap的程序。

我试过这段代码:

class Question extends Entity with HasTags { 
    @Reference 
    var tags2: java.util.List[Tag] = new java.util.ArrayList() 
} 

并查看Java Decompiler字节码,它会显示:

public class Question extends Entity implements HasTags { 
     @Reference 
     private java.util.List tags; 
     @Reference 
     private java.util.List<models.Tag> tags2; 
} 

我们可以看到tags2包含Tag,但tags没有。

和接口HasTags是:

public abstract interface HasTags extends ScalaObject 
{ 
    public abstract List<Tag> tags(); 

    @TraitSetter 
    public abstract void tags_$eq(List<Tag> paramList); 
} 

我们可以看到,方法tags()的返回值是List<Tag>,但是场tags没有。

由于morphia通过字段获取信息,因此无法正常工作。

回答

2

这就是javap显示内容的方式。这并不意味着签名不存在。

scala> classOf[HasTags].getMethod("tags").getGenericReturnType 
res0: java.lang.reflect.Type = java.util.List<Tag> 

你就是这么知道的。你也可以在常量池中看到它。

const #3 = Asciz tags; 
const #4 = Asciz ()Ljava/util/List;; 
const #5 = Asciz ()Ljava/util/List<LTag;>;; 
+0

谢谢你,看看我更新的问题 – Freewind 2011-05-07 11:25:21

1

我不知道还有什么要显示的:它不能在这个输出中说“Tag”,除非签名存在。领域和方法。

% cat a.scala 
class Tag 
class Ref { 
    var tags: java.util.List[Tag] = new java.util.ArrayList() 
} 
% scalac281 a.scala 
% scala281 
Welcome to Scala version 2.8.1.final (Java HotSpot(TM) 64-Bit Server VM, Java 1.6.0_22). 
Type in expressions to have them evaluated. 
Type :help for more information. 

scala> classOf[Ref].getDeclaredField("tags").getGenericType 
res0: java.lang.reflect.Type = java.util.List<Tag> 

scala> classOf[Ref].getMethod("tags").getGenericReturnType 
res1: java.lang.reflect.Type = java.util.List<Tag>