【问题标题】:Create a custom event in Java在 Java 中创建自定义事件
【发布时间】:2011-09-10 08:08:01
【问题描述】:

我想在 Java 中做这样的事情,但我不知道怎么做:

当事件“object 1 say 'hello'”发生时, 然后对象 2 通过说“你好”来响应该事件。

谁能给我一个提示或示例代码?

【问题讨论】:

标签: java events listener handler


【解决方案1】:

您可能想查看observer pattern

这里有一些示例代码可以帮助您入门:

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: Creating a custom event

【讨论】:

  • stackoverflow.com/suggested-edits/237242 没有通过有正当理由吗?它显示了如何使用最初提出的问题的 2 个类来执行此操作。
  • 如果多个线程正在生成源事件,会正确同步吗?
  • @GlassGhost:它被拒绝了,因为它基本上是完全重写。如果他们修复错别字和格式以及断开的链接等,对其他人的答案进行编辑是很好的,但他们不应该从根本上改变内容。 (一些例外情况适用于标有“社区 wiki”的帖子。)
  • java没有内置的东西吗?我真的更喜欢以抽象模式执行此操作,而不是为每个事件实现 for 循环。
  • 随着 java.util.Observer 从 Java 9 中被弃用,在实现自定义事件方面是否有更好的选择?
【解决方案2】:

您想要的是observer pattern 的实现。你可以完全自己做,或者使用像java.util.Observerjava.util.Observable这样的java类

【讨论】:

【解决方案3】:

您可能希望通过 3 种不同的方式进行设置:

  1. Thrower 内部 Catcher
  2. Catcher 内部 Thrower
  3. ThrowerCatcher 在此示例中位于另一个类中 Test

THE WORKING GITHUB EXAMPLE I AM CITING 默认为选项 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 . . .
}

【讨论】:

  • @GlassGhost:问题是main 是静态的,在静态函数中没有this 这样的东西。您需要在某处创建new Catcher1(),然后传递该实例。 1.5 也不允许在静态上下文中使用this;我很确定它从未被允许。
  • @GlassGhost:使用this 的代码在构造函数中,而不是在main 中。这就是它起作用的原因。将其移至main,我保证不会。这就是人们一直试图告诉你的,也是你的答案试图做的。我不在乎 github 上的内容——我关心 SO 上的内容。你在 SO 上的东西已经坏了。
  • @GlassGhost:我不认为你的回答总体上是不充分的。我看到的问题是代码不能按原样工作——您正在尝试使用来自mainthis,它不会在任何已发布的Java 版本中编译。如果该部分是在构造函数中,或者如果 main 创建了一个 new Catcher1() 并使用它而不是 this,它应该可以工作,即使在 1.6+ 中也是如此。
  • @GlassGhost:“声明为static的方法称为类方法。类方法总是在不引用特定对象的情况下被调用。尝试使用关键字@引用当前对象987654348@ 或关键字 super 或引用类方法主体中任何周围声明的类型参数会导致编译时错误。” -- JLS for Java 5, §8.4.3.2
  • 这是我见过的最奇怪的代码风格之一
【解决方案4】:

下面的不完全一样但是差不多,我一直在找一个sn-p来添加对接口方法的调用,结果发现了这个问题,所以决定添加这个sn-p给正在搜索的人它和我一样发现了这个问题:

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

【讨论】:

    【解决方案5】:

    术语

    • 听众是观察者/处理者
    • dispatcher 是主题/观察者容器

    通常,当人们实现 observer pattern 时,他们需要 dispatcher 存在,然后任何 listener 才能订阅它。但是有一个更好的方法叫做Signals

    Signals 是一个事件库。它通过引入一个允许注册侦听器和调度事件的 Signal 对象来解耦调度程序的侦听器。信号是通过代理从接口自动创建的。它负责管理侦听器的所有样板代码,此外还添加了一些不错的糖代码 API。

    interface Chat{
        void onNewMessage(String s);    
    }
    
    class Foo{
        Signal<Chat> chatSignal = Signals.signal(Chat.class);
        
        void bar(){
            chatSignal.addListener( s-> Log.d("chat", s) ); // logs all the messaged to Logcat
        }
    }
    
    class Foo2{
        Signal<Chat> chatSignal = Signals.signal(Chat.class);
        
        void bar2(){
            chatSignal.dispatcher.onNewMessage("Hello from Foo2"); // dispatches "Hello from Foo2" message to all the listeners
        }
    }
    

    在本例中,信号是从Chat 接口自动创建的。它允许Foo 注册它并允许Foo2 发送新消息而无需交互。

    免责声明:我是 Signals 的作者。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-08-28
      • 1970-01-01
      • 2014-06-14
      • 2015-10-01
      • 1970-01-01
      • 2012-07-24
      • 2019-01-11
      相关资源
      最近更新 更多