Groovy静态泛型类型

时间:2010-10-09 18:07:06

标签: java generics activerecord groovy

我一直在玩摆脱DAO而不是像Java中的实体那样的ActiveRecord,但是泛型不允许我拥有我想要的全部功能(比如静态查找器)。以某种方式Groovy,但我很困惑为什么。鉴于以下内容:

class ActiveRecord<T> {
   static Class<T> genericType;
   ActiveRecord() {
     genericType = ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
   }
   static T find(Serializable id) { return EntityManagerHolder.find(genericType, id); }
   void save() { EntityManagerHolder.persist(this); }
}

@Entity @Table(name="TEST")
class FakeTable extends ActiveRecord<FakeTable> {
   @Id @GeneratedValue(strategy = GenerationType.AUTO)
   Long id;
   String status;
   String type;
   static void main(args) {
      FakeTable t = new FakeTable();
      t.status = "TESTING";
      t.save();
      println FakeTable.find(t.id);
   }
}

此代码有效(使用JPA的东西除外),但我不知道为什么我能够声明

static Class<T> genericType;

在编译实际的Java类之前编译器是否做了一些魔术?也许groovy编译器将T替换为生成的Java类中的实际类名?

在严格的Java中,我可以从find方法返回类型和类声明中访问泛型类型,但两者都被擦除为Object。这是有道理的,Groovy做同样的事情,但在Java中,上面的行错误输出类似于'无法引用非静态T'的消息。

2 个答案:

答案 0 :(得分:2)

Groovy不是静态类型的。我认为你会发现它在编译时删除了T,并且甚至没有想到它不在范围内;这与Groovy无关。

答案 1 :(得分:1)

您将遇到的主要问题是在Java和Groovy中,静态方法不会被继承。 Grails(和其他Java框架)通过操作字节代码在运行时生成这些方法来解决这个问题。

使用groovy,在程序启动时,您可以尝试循环遍历所有ActiveRecord子类和attaching the static finders to their meta class。如果您使用ActiveRecord类来查找子类并至少获取静态查找器,您仍然可以通过查看ActiveRecord类本身来告诉他们继承了哪些方法。

编辑:

在我看来,您还可以在ActiveRecord类上实现methodMissing,以尝试在ActiveRecord对象上查找该方法。你只需要注意不要设置无限循环。