Crea un evento personalizzato in Java


Risposte:


421

Probabilmente vuoi esaminare il modello di osservatore .

Ecco un po 'di codice di esempio per iniziare:

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..."
    }
}

Articolo correlato: Java: creazione di un evento personalizzato


C'è un motivo legittimo che stackoverflow.com/suggested-edits/237242 non è stato esaminato? Mostra come fare questo con 2 classi come la domanda iniziale.
GlassGhost

2
Che cosa succede se più thread generano gli eventi di origine, questo verrà sincronizzato correttamente?
Mike G,

Dipende dalla sirmentazione. Ogni ascoltatore verrà avvisato in base all'ordine che ha registrato. (A proposito, non capisco cosa intendi con più thread qui. Il codice dell'ascoltatore verrà emesso sullo stesso thread che ha causato l'evento.)
aioobe

8
@GlassGhost: è stato rifiutato perché era sostanzialmente una riscrittura totale. Le modifiche alla risposta di qualcun altro sono utili se correggono errori di battitura e formattazione e collegamenti interrotti e simili, ma non dovrebbero cambiare radicalmente il contenuto. (Alcune eccezioni si applicano ai post contrassegnati come "wiki della comunità".)
cHao

1
Java non ha cose integrate per questo? Preferirei davvero farlo in un modello astratto, non implementare il loop per ogni evento.
Tomáš Zato - Ripristina Monica il


21

Ci sono 3 modi diversi in cui potresti voler impostare:

  1. Thrower all'interno Catcher
  2. Catcher all'interno Thrower
  3. Throwere Catcherall'interno di un'altra classe in questo esempioTest

L'ESEMPIO GITHUB DI LAVORO CHE SONO CITING Il valore predefinito è Opzione 3, per provare gli altri a decommentare semplicemente il "Optional" blocco di codice della classe che si desidera essere principale e impostare quella classe come${Main-Class}variabile nelbuild.xmlfile:

4 cose necessarie per lanciare il codice laterale:

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 Cose necessarie in un file di classe per ricevere eventi da una classe

/*_______________________________________________________________*/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: il problema è mainstatico e non esiste thisuna funzione statica. Devi crearne uno new Catcher1()da qualche parte e passare invece quell'istanza. 1.5 non ha permesso neanche thisin un contesto statico; sono abbastanza sicuro che non sia mai stato permesso.
cHao,

6
@GlassGhost: il codice che utilizza thisè in un costruttore, non in main. Ecco perché funziona. Spostalo in main, e ti garantisco che non lo farà. Questo è ciò che le persone hanno cercato di dirti e ciò che la tua risposta sta cercando di fare. Non me ne frega niente di quello che c'è su Github - mi importa cosa c'è su SO. E quello che hai su SO è rotto.
cao

7
@GlassGhost: non credo che la tua risposta sia complessivamente inadeguata. Il problema che vedo con essa è che il codice non funzionerà come è - si sta cercando di usare thisda main, che non verrà compilato in ogni versione rilasciata di Java. Se invece quella parte fosse in un costruttore, o se maincreata new Catcher1()e usata e invece di quella this, dovrebbe funzionare, anche in 1.6+.
cao

6
@GlassGhost: "Un metodo dichiarato staticviene chiamato metodo di classe. Un metodo di classe viene sempre invocato senza riferimento a un oggetto particolare. Un tentativo di fare riferimento all'oggetto corrente utilizzando la parola chiave thiso la parola chiave supero di fare riferimento ai parametri di tipo di qualsiasi ambiente circostante la dichiarazione nel corpo di un metodo di classe genera un errore in fase di compilazione. " - JLS per Java 5, §8.4.3.2
cHao,

31
Questo è uno degli stili di codice più strani che abbia mai visto
Eric

4

Quanto segue non è esattamente lo stesso ma simile, stavo cercando uno snippet per aggiungere una chiamata al metodo dell'interfaccia, ma ho trovato questa domanda, quindi ho deciso di aggiungere questo snippet per coloro che lo cercavano come me e ho trovato questa domanda :

 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);
        }    
    }

L'utilizzo è il seguente:

myClassObj.setDataLoadFinishedListener(new MyClass.DataLoadFinishedListener() {
            @Override
            public void onDataLoadFinishedListener(int data_type) {
                }
            });
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.