你可以在GWT客户端使用Java反射API吗?

24

是否可以在GWT客户端使用Java反射API?我想使用反射在JavaBean上查找属性值。这是否可行?

6个回答

13
你可以使用GWT Generators功能来在GWT编译阶段生成代码。
你想要内省的bean可以扩展一个具有定义方法的类。
public Object getProperty(String propertyName){}

我们将这个类称为IntrospectionBean

假设您已经定义了您的bean:

public class MyBean extends IntrospectionBean {
    private String prop1;
    private String prop2;
}

GWT生成器将可以访问MyBean的所有字段,并且在GWT编译时期间,通过迭代MyBean的所有字段来生成getProperty(String propertyName)方法。

生成的类可能像这样:

public class MyBean extends IntrospectionBean {
    private String prop1;
    private String prop2;

    public Object getProperty(String propertyName) {
        if ("propr1".equals(propertyName)) {
            return prop1;
        }
        if ("propr2".equals(propertyName)) {
            return prop2;
        }

        return null;
    }
}
你可以简单地使用myBean.getProperty("prop1") 来根据属性名称在运行时检索属性。 这里有一个实现GWT生成器的例子。

12

10

由于GWT代码被翻译成JavaScript,因此不支持直接使用反射API。

有一个名为GWT-Reflection的小项目,可以在GWT中使用反射。


2
有趣的项目。注意:在使用之前,请确保您可以接受GPL许可证。 - Chris Lercher
不行,因为许可证的问题不能使用它。不管怎样,感谢你提供的指导。 - Farouk Alhassan
请注意下面我的评论... 我已经发布了一个Apache许可证的反射API的完整实现:https://github.com/WeTheInternet/xapi/tree/master/gwt/gwt-reflect - Ajax

2

2
我已将我的gwt-reflection库公开。

https://github.com/WeTheInternet/xapi/tree/master/gwt/gwt-reflect https://github.com/WeTheInternet/gwt-sandbox/tree/xapi-gwt/user/src/com/google/gwt/reflect

由于使用Gwt时出现了类路径问题,我试图让Gwt选择我的Class.java版本而不是它自己的版本。最终,我只好fork了Gwt,并添加了Java 8和反射支持。现在,我维护net.wetheinter:gwt-*:2.7.0,其中包含这个支持(在Gwt 2.8发布后,我会发布一个2.8版本)。
它支持三个反射级别:
1. 单体反射:
// Embeds all data needed to perform reflection into hidden fields of class
GwtReflect.magicClass(SomeClass.class);
SomeClass.getField(fieldName).set(null, 1);

轻量级:
// Allows direct reflection, provided ALL parameters are literals, or traced to literals
SomeClass.class.getField("FIELD_NAME").set(null, 1);

轻量级模式:
// Skips creating a Field object entirely, and just invokes the accessor you want
// All params must be literals here as well
GwtReflect.set(SomeClass.class, "FIELD_NAME", null, 1);

这些示例也适用于方法和构造函数。目前有基本的注释支持,未来还会有更多的支持。

0
如果您只是想使用反射来获取私有字段,请考虑改用jsni(javascript native interface);它没有公共或私有的概念,因此您可以像这样随意获取任何内容:
package com.foo;

class SomeClass {
    private String someField;
    private static int someInt;
}

//accessors:
native String ripField(SomeClass from)
/*-{
  return from.@com.foo.SomeClass::someField;
}-*/;
native int ripInt()
/*-{
  return @com.foo.SomeClass::someInt;
}-*/;

此外,我正在完成java.lang.Class newInstance / 反射的仿真。

如果您想玩一下,我将在大约两天后在这里发布一个链接。

它需要您通过一个方法传递一个类,我将其路由到自定义生成器 (像GWT.create,但它返回一个生成的java.lang.Class,其中包含指向jsni方法/字段的字段和方法访问器。 :)


当我第一次看到这个答案时,我感到非常兴奋,但进一步检查后发现它有严重的缺陷,例如必须事先知道类类型(无法在泛型中使用),并且必须为每个字段提供一个“rip”方法,而不是提供字段名称。最好还是使用普通的JavaBean getter。 - NickJ
除非您无法控制需要访问的代码,并且不想维护其他人的代码副本以访问私有成员。此外,泛型如何在反射方面有所帮助?泛型通过擦除工作,而jsni也匹配它。 - Ajax
只是另一个想法,你可以生成所有这些。我维护了一个公共的GWT构建版本,net.wetheinter:gwt-*:2.7.0,它通过魔术方法注入实现了反射。这是Gwt的一个分支,因为我不得不劫持GWT.create机制,以查找并替换通过类/字符串字面量完成的反射,使用像上面示例中的生成代码。曾经有一个版本可以让您使用GWT.create增强类,以避免入侵编译器,但没有足够的兴趣来维护它(它还会生成大量代码)。 - Ajax

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接