0

私はしばらくの間Bukkitプラグインプロジェクトに取り組んできましたが、ついに正式なリリースを行うことにしました。そのため、プロジェクトに関するすべてを文書化するためのクレイジーなスクランブルで、APIを使用したい人のためにいくつかのAPIをクリーンアップすることにしました。今、私は1つの問題で壁にぶつかりました。

基本的に、この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.getDeclaredField()の代わりにa.getField()を試しましたが、同じ問題が発生します。name変数とtracker変数はどちらも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)
4

3 に答える 3

1

インターフェイスはフィールドを宣言できません、それは実際のコードですか?

あなたが直面している問題は、getDeclaredFieldメソッドがその指定された名前のフィールドを取得するが、スーパークラスを検索しないことです。質問の反映部分に答えるため.getSuperclass()に、そのフィールドを宣言するクラスに到達するまで、Classオブジェクト(およびそのオブジェクトのスーパークラスなど)で継続的に呼び出すヘルパーメソッドを作成することをお勧めします。(編集、指定された例に一致するように:静的フィールドを取得するには、を使用する必要がありますfield.get(null);。)

ただし、より適切な解決策は、インターフェイスにいくつかのgetterメソッドを宣言させることです-Tracker getTracker();およびString getName();

于 2013-01-02T17:45:39.217 に答える
0

Beanとして構造化されたクラスオブジェクトを使用している場合は、春にapache-commonsまたはBeanWrapper(名前が100%確実ではない)のBeanUtilsを確認する必要があります。舞台裏では、低レベルの反射とイントロスペクションを処理するため、値を取得するための単純なメソッド呼び出しを作成するだけです。

registerActionを見て、渡されたクラスオブジェクトをキャストしようとすると、下流で頭痛が発生する可能性があります。

ジェネリックスを使用して書き直し、引数をTrackerクラスオブジェクトにすることができると思います

public static void registerAction(final Class<Tracker> a) {

また、使用する前に、クラスにメソッドまたはフィールドが含まれているかどうかを確認するためのチェックをいくつか追加することもできます。

于 2013-01-02T22:11:18.423 に答える
0

私は自分の答えを見つけました。結局、使用する準備ができているMetricsインスタンスができる前に、Metricsインスタンスで#addCustomData()を実行しようとしていました。Actions.init()をコントローラーの数行下に移動する必要がありました:)

于 2013-01-04T22:57:57.143 に答える