I';我在Java项目中遇到了一些问题

I';我在Java项目中遇到了一些问题,java,reflection,Java,Reflection,我在一个Bukkit插件项目上工作了一段时间,最后我决定发布一个正式版本。因此,在我疯狂地争先恐后地记录我的项目的所有内容时,我决定为那些想使用它们的人清理一些API。现在,我遇到了一个问题 基本上,在这个API中,您必须实现一个接口,然后将您的实现注册到一个类中,该类管理每个实现,并使用插件中捆绑的PluginMetrics检查/注册另一个变量 这是我的界面,“名称”和“跟踪器”字段是关注的字段: public interface IAction { /** * Name

我在一个Bukkit插件项目上工作了一段时间,最后我决定发布一个正式版本。因此,在我疯狂地争先恐后地记录我的项目的所有内容时,我决定为那些想使用它们的人清理一些API。现在,我遇到了一个问题

基本上,在这个API中,您必须实现一个接口,然后将您的实现注册到一个类中,该类管理每个实现,并使用插件中捆绑的PluginMetrics检查/注册另一个变量

这是我的界面,“名称”和“跟踪器”字段是关注的字段:

public interface IAction {

    /**
     * Name of the action.
     */
    String name = null;
    /**
     * Stores args passed to the action by the player.
     */
    String[] args = null;
    /**
     * Holds the Metrics tracker object.
     */
    Tracker tracker = null;

    ...
}
这里是我所有问题出现的方法(和init()方法):

public static void registerAction(final Class a) {
    try {
        store.put((String) a.getField("name").get(a), a);
        log.exDebug(String.format("Action %s (%s) was registered.", (String) a.getField("name").get(a), a.getCanonicalName()));
        try {
            Tracker metric = (Tracker) a.getField("tracker").get(a);
            try {
                OpenAuth.getMetrics().addCustomData(metric);
                log.exDebug(String.format("Registered Metrics data tracker [%s] from %s.", metric.getColumnName(), a.getCanonicalName()));
            } catch (java.lang.Exception e) {
                log.info("Exception occurred while registering Action data tracker.");
            }
        } catch (java.lang.Exception e) {
            log.info("Exception occurred while registering Action data tracker.");
            // e.printStackTrace();
        }
    } catch (java.lang.Exception e) {
        log.info("Exception occurred while registering an Action.");
        e.printStackTrace();
    }
}

public static void init() {
    for (Actions a : Actions.values()) {
        try {
            registerAction(a.getAction());
        } catch (java.lang.Exception e) {
            log.info("Exception occurred while initialising Actions enumerator.");
            e.printStackTrace();
        }
    }
    for (Object ob : classLoader.load().getClasses()) {
        Class c = null;
        try {
            c = (Class) ob;
        } catch (java.lang.Exception e) {
            log.info("Exception occurred while casting up external Action.");
            e.printStackTrace();
        }
        try {
            registerAction(c);
        } catch (java.lang.Exception e) {
            log.info("Exception occurred while registering external Action.");
            e.printStackTrace();
        }
    }
}
以及一个示例实现:

public class FreezeStick implements IAction {

    public static final String name = "freeze";
    public static final Tracker tracker = new Tracker("FreezeStick");

    private String[] args = null;
    private Session attached;
    private SessionController sc;
    private final LogHandler log = new LogHandler();
    private final String permissible = "openauth.action.freeze";
    private OAServer server;
    private boolean used = false;

    protected OAPlayer sender;
    protected OAPlayer target;

    public FreezeStick(OAServer server, Session attached) {
        this.server = server;
        this.sc = server.getController().getSessionController();
        this.attached = attached;
        this.setSender(this.attached.getPlayer());
    }

-- etc.. --
每次
Tracker metric=(Tracker)a.getDeclaredField(“Tracker”).get(a)发生时,它是
报告为
null
。我尝试使用.getField()而不是.getDeclaredField(),但问题相同。name和tracker变量在实现中声明时都会接收到
private、static和final
,并且在name变量上使用.getField()从我第一次写这篇文章以来一直工作得很好

如果有人能给我指出正确的方向,我将不胜感激:)

此外,如果有助于更好地解决我的问题,则会出现以下例外情况:

2013-01-02 10:48:10 [INFO] [OpenAuth-debug] Action ban (me.maiome.openauth.actions.BanStick) was registered.
2013-01-02 10:48:10 [INFO] [OpenAuth] Exception occurred while adding Action data tracker.
2013-01-02 10:48:10 [SEVERE] java.lang.NullPointerException
2013-01-02 10:48:10 [SEVERE]    at me.maiome.openauth.actions.Actions.registerAction(Actions.java:65)
2013-01-02 10:48:10 [SEVERE]    at me.maiome.openauth.actions.Actions.init(Actions.java:104)
2013-01-02 10:48:10 [SEVERE]    at me.maiome.openauth.bukkit.OpenAuth.onEnable(OpenAuth.java:230)
2013-01-02 10:48:10 [SEVERE]    at org.bukkit.plugin.java.JavaPlugin.setEnabled(JavaPlugin.java:217)
2013-01-02 10:48:10 [SEVERE]    at org.bukkit.plugin.java.JavaPluginLoader.enablePlugin(JavaPluginLoader.java:457)
2013-01-02 10:48:10 [SEVERE]    at org.bukkit.plugin.SimplePluginManager.enablePlugin(SimplePluginManager.java:381)
2013-01-02 10:48:10 [SEVERE]    at org.bukkit.craftbukkit.v1_4_6.CraftServer.loadPlugin(CraftServer.java:278)
2013-01-02 10:48:10 [SEVERE]    at org.bukkit.craftbukkit.v1_4_6.CraftServer.enablePlugins(CraftServer.java:260)
2013-01-02 10:48:10 [SEVERE]    at org.bukkit.craftbukkit.v1_4_6.CraftServer.<init>(CraftServer.java:214)
2013-01-02 10:48:10 [SEVERE]    at net.minecraft.server.v1_4_6.PlayerList.<init>(PlayerList.java:52)
2013-01-02 10:48:10 [SEVERE]    at net.minecraft.server.v1_4_6.DedicatedPlayerList.<init>(SourceFile:11)
2013-01-02 10:48:10 [SEVERE]    at net.minecraft.server.v1_4_6.DedicatedServer.init(DedicatedServer.java:104)
2013-01-02 10:48:10 [SEVERE]    at net.minecraft.server.v1_4_6.MinecraftServer.run(MinecraftServer.java:399)
2013-01-02 10:48:10 [SEVERE]    at net.minecraft.server.v1_4_6.ThreadServerApplication.run(SourceFile:849)
2013-01-02 10:48:10[INFO][OpenAuth debug]操作禁令(me.maiome.OpenAuth.actions.BanStick)已注册。
2013-01-02 10:48:10添加操作数据跟踪器时发生[INFO][OpenAuth]异常。
2013-01-02 10:48:10[严重]java.lang.NullPointerException
2013-01-02 10:48:10[Severy]at me.maiome.openauth.actions.actions.registerAction(actions.java:65)
2013-01-02 10:48:10[Severy]at me.maiome.openauth.actions.actions.init(actions.java:104)
2013-01-02 10:48:10[严重]攻击我.maiome.openauth.bukkit.openauth.onEnable(openauth.java:230)
2013-01-02 10:48:10[严重]见org.bukkit.plugin.java.JavaPlugin.setEnabled(JavaPlugin.java:217)
2013-01-02 10:48:10[严重]见org.bukkit.plugin.java.JavaPluginLoader.enablePlugin(JavaPluginLoader.java:457)
2013-01-02 10:48:10[严重]见org.bukkit.plugin.SimplePluginManager.enablePlugin(SimplePluginManager.java:381)
2013-01-02 10:48:10[严重]见org.bukkit.craftbukkit.v1_4_6.CraftServer.loadPlugin(CraftServer.java:278)
2013-01-02 10:48:10[严重]见org.bukkit.craftbukkit.v1_4_6.CraftServer.enablePlugins(CraftServer.java:260)
2013-01-02 10:48:10[严重]见org.bukkit.craftbukkit.v1_4_6.CraftServer.(CraftServer.java:214)
2013-01-02 10:48:10[严重]在net.minecraft.server.v1_4_6.PlayerList.(PlayerList.java:52)
2013-01-02 10:48:10[严重]在net.minecraft.server.v1_4_6.专用玩家列表。(源文件:11)
2013-01-02 10:48:10[严重]在net.minecraft.server.v1_4_6.indivatedServer.init(indivatedServer.java:104)
2013-01-02 10:48:10[严重]在net.minecraft.server.v1_4_6.MinecraftServer.run(MinecraftServer.java:399)
2013-01-02 10:48:10[严重]在net.minecraft.server.v1_4_6.ThreadServerApplication.run(源文件:849)

接口不能声明字段,这是实际代码吗

您面临的问题是
getDeclaredField
方法将获得一个具有给定名称的字段,但不会搜索超类。为了回答问题的反射部分,我建议您创建一个helper方法,该方法将在类对象(以及该对象的超类等)上不断调用
.getSuperclass()
,直到到达声明该字段的类为止。 (编辑,以匹配给定示例:要获取静态字段,应使用
field.get(null);


然而,更合适的解决方案是让接口声明一些getter方法-
Tracker getTracker()
字符串getName()

如果您使用的类对象是以bean的形式构造的,那么您应该看看ApacheCommons中的BeanUtils或spring中的BeanRapper(名称不是100%确定)。在幕后,它们为您处理低级反射和内省,因此您所要做的就是编写一个简单的方法调用来检索值

查看registerAction,您只需尝试强制转换传入的类对象,这可能会导致下游出现一些头痛

我认为您可能能够使用泛型重写,以强制参数成为Tracker类对象

public static void registerAction(final Class<Tracker> a) {
publicstaticvoidregisterAction(最终a类){

您还可以在尝试使用某个类之前添加一些检查,以查看该类是否包含方法或字段。

我找到了答案。事实证明,在准备使用Metrics实例之前,我正试图在Metrics实例上运行#addCustomData()。只需移动Actions.init()我的控制器中有几行:)

事实是,registerAction()方法可以完全正确地获取名称!但是每次该方法尝试获取该方法尝试获取跟踪器时,它都会给出一个null。这有助于澄清我是否提供了整个操作API吗?如果
getDeclaredField
不是返回
null
,而是
get
的字段,那么该字段的值很可能是这是空的。