Отсутствует информация общего типа полей в признаках?

#generics #scala #morphia #traits

#общие сведения #scala #morphia #Трейты

Вопрос:

Я обнаружил эту проблему при использовании Morphia в scala. Он проверяет поля класса путем отражения и получает необходимую информацию о типе для сопоставления.

Но если я использую 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 {

}
  

Я скомпилировал файл scala и получил несколько файлов классов java. Затем я использую java decompiler, чтобы просмотреть содержимое байтовых кодов java:

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

Вы можете видеть, что здесь ее нет Tag , поэтому Morphia завершится неудачей.

Я использовал scala 2.8.1 . Есть ли какой-нибудь способ это исправить?


Обновить

@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 получает информацию по полям, она не может работать корректно.

Ответ №1:

Вот как 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;>;;
  

Ответ №2:

Я не знаю, что еще показать: в этом выводе не может быть указано «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>