Javaでカスタムイベントを作成する


193

私はJavaでこのようなことをしたいのですが、方法がわかりません:

イベント「object 1 say 'hello'」が発生すると、オブジェクト2は「hello」と言ってそのイベントに応答します。

誰かが私にヒントやサンプルコードをくれますか?



回答:


421

おそらく、オブザーバーパターンを調べたいと思います。

ここにあなた自身を始めるためのいくつかのサンプルコードがあります:

import java.util.*;

// An interface to be implemented by everyone interested in "Hello" events
interface HelloListener {
    void someoneSaidHello();
}

// Someone who says "Hello"
class Initiater {
    private List<HelloListener> listeners = new ArrayList<HelloListener>();

    public void addListener(HelloListener toAdd) {
        listeners.add(toAdd);
    }

    public void sayHello() {
        System.out.println("Hello!!");

        // Notify everybody that may be interested.
        for (HelloListener hl : listeners)
            hl.someoneSaidHello();
    }
}

// Someone interested in "Hello" events
class Responder implements HelloListener {
    @Override
    public void someoneSaidHello() {
        System.out.println("Hello there...");
    }
}

class Test {
    public static void main(String[] args) {
        Initiater initiater = new Initiater();
        Responder responder = new Responder();

        initiater.addListener(responder);

        initiater.sayHello();  // Prints "Hello!!!" and "Hello there..."
    }
}

関連記事:Java:カスタムイベントの作成


stackoverflow.com/suggested-edits/237242が実行されなかった正当な理由はありますか?これは、最初に質問された2つのクラスでこれを行う方法を示しています。
GlassGhost

2
複数のスレッドがソースイベントを生成している場合、これは正しく同期されますか?
Mike G

状況によって異なります。各リスナーは、登録した順序に従って通知されます。(ところで、ここでは複数のスレッドの意味がわかりません。リスナーコードは、イベントを発生させたのと同じスレッドで実行されます。)
aioobe

8
@GlassGhost:基本的に完全に書き直されたため、拒否されました。他人の回答の編集は、タイプミスや書式設定、リンク切れなどを修正する場合に有効ですが、内容を根本的に変更するべきではありません。(「コミュニティウィキ」とマークされた投稿には、いくつかの例外が適用されます。)
cHao '23年

1
Javaにはこれのための組み込みのものはありませんか?私はこれをすべてのイベントにforループを実装するのではなく、抽象的なパターンで実行することを本当に望んでいます。
トマーシュZato -復活モニカ


21

これを設定する方法は3つあります。

  1. Thrower の中に Catcher
  2. Catcher の中に Thrower
  3. ThrowerそしてCatcher、この例では別のクラスの内部Test

動作しているGITHUBの例私はデフォルトをオプション3に設定しています。他のものを試すには、Optionalメインにしたいクラスの""コードブロックのコメントを外し、そのクラスをファイル内の${Main-Class}変数として設定しbuild.xmlます。

4サイドコードをスローするために必要なもの:

import java.util.*;//import of java.util.event

//Declaration of the event's interface type, OR import of the interface,
//OR declared somewhere else in the package
interface ThrowListener {
    public void Catch();
}
/*_____________________________________________________________*/class Thrower {
//list of catchers & corresponding function to add/remove them in the list
    List<ThrowListener> listeners = new ArrayList<ThrowListener>();
    public void addThrowListener(ThrowListener toAdd){ listeners.add(toAdd); }
    //Set of functions that Throw Events.
        public void Throw(){ for (ThrowListener hl : listeners) hl.Catch();
            System.out.println("Something thrown");
        }
////Optional: 2 things to send events to a class that is a member of the current class
. . . go to github link to see this code . . .
}

2クラスからイベントを受け取るためにクラスファイルに必要なもの

/*_______________________________________________________________*/class Catcher
implements ThrowListener {//implement added to class
//Set of @Override functions that Catch Events
    @Override public void Catch() {
        System.out.println("I caught something!!");
    }
////Optional: 2 things to receive events from a class that is a member of the current class
. . . go to github link to see this code . . .
}

6
@GlassGhost:問題はmain静的でありthis、静的関数のようなものはありません。new Catcher1()どこかに作成し、代わりにそのインスタンスを渡す必要があります。1.5 thisでは、静的コンテキストでも使用できませんでした。許可されたことはないと思います。
cHao 2014年

6
@GlassGhost:を使用するコードthisは、コンストラクタではなく、コンストラクタ内にありmainます。それが機能する理由です。に移動しmainます。そうしないことを保証します。それは人々があなたに伝えようとしてきたことであり、あなたの答えが何をしようとしているかです。私はgithubに何があるか気にしません-私は何がSOにあるか気にします。そして、あなたがSOで持っているものが壊れています。
cHao 2014

7
@GlassGhost:あなたの答えは全体として不十分だとは思いません。私が目にする問題は、コードがそのままでは機能しないことです。リリースされたバージョンのJavaでコンパイルできないthisfrom を使用しようとしてmainいます。その部分が代わりにコンストラクターにあった場合、またはをmain作成しnew Catcher1()ての代わりにthisそれを使用した場合、1.6以降でも機能するはずです。
cHao 2014

6
@GlassGhost: "宣言さstaticれたメソッドはクラスメソッドと呼ばれます。クラスメソッドは常に特定のオブジェクトを参照せずに呼び出されます。キーワードthisまたはキーワードを使用して現在のオブジェクトをsuper参照するか、周囲のタイプパラメータを参照しようとしましたクラスメソッドの本体で宣言すると、コンパイル時エラーが発生します。」- Java 5のためのJLS、§8.4.3.2
チャオ

31
これは、私が今まで見た中で最も奇妙なコードスタイルの1つです
Eric

4

以下はまったく同じではありませんが類似しています。インターフェイスメソッドへの呼び出しを追加するスニペットを検索していましたが、この質問を見つけたので、私のようにそれを検索していた人のためにこのスニペットを追加することにし、この質問を見つけました:

 public class MyClass
 {
        //... class code goes here

        public interface DataLoadFinishedListener {
            public void onDataLoadFinishedListener(int data_type);
        }

        private DataLoadFinishedListener m_lDataLoadFinished;

        public void setDataLoadFinishedListener(DataLoadFinishedListener dlf){
            this.m_lDataLoadFinished = dlf;
        }



        private void someOtherMethodOfMyClass()
        {
            m_lDataLoadFinished.onDataLoadFinishedListener(1);
        }    
    }

使用法は次のとおりです。

myClassObj.setDataLoadFinishedListener(new MyClass.DataLoadFinishedListener() {
            @Override
            public void onDataLoadFinishedListener(int data_type) {
                }
            });
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.