我一直在研究Bukkit插件项目,我终于决定正式发布了。因此,在我疯狂争夺文档的所有内容时,我决定为想要使用它们的人清理一些API。现在,我遇到了一个问题。
基本上,在此API中,您必须实现一个接口,然后使用管理每个实现的类注册您的实现,并使用插件中捆绑的PluginMetrics检查/注册另一个变量。
这是我的界面,“name”和“tracker”字段是关注的字段:
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
。我尝试过使用a.getField()而不是a.getDeclaredField(),但同样的问题。名称和跟踪器变量在实现中声明时都会收到private, static, and final
,并且自从我第一次写这篇文章以来,在name变量上使用a.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)
答案 0 :(得分:1)
接口不能声明字段,是实际代码吗?
您面临的问题是getDeclaredField
方法将获得具有该给定名称的字段,但不会搜索超类。为了回答问题的反思部分,我建议你创建一个辅助方法,它将不断地调用Class对象(以及该对象的超类等)上的.getSuperclass()
,直到你到达一个声明该字段的类。
(编辑,以匹配给定示例:要获取静态字段,您应使用field.get(null);
。)
然而,更合适的解决方案是使界面声明一些getter方法 - Tracker getTracker();
和String getName();
。
答案 1 :(得分:0)
如果您正在使用结构为bean的类对象,那么您应该在spring中查看apache-commons中的BeanUtils或BeanWrapper(名称上不是100%确定)。在幕后,他们为您处理低级反射和内省,所以您所要做的就是编写一个简单的方法调用来检索值。
查看registerAction,您只需尝试转换传入的类对象,这可能会导致一些头部疼痛。
我认为您可以使用泛型重写强制参数成为Tracker类对象
public static void registerAction(final Class<Tracker> a) {
在尝试使用它们之前,您还可以添加一些检查以查看某个类是否包含方法或字段。
答案 2 :(得分:0)
我找到了答案。事实证明,在尝试使用Metrics实例之前,我试图在Metrics实例上运行#addCustomData()。只需要在我的控制器中将Actions.init()向下移动几行:)