【问题标题】:JDK interface for processing a generic parameter处理泛型参数的JDK接口
【发布时间】:2011-12-13 01:39:52
【问题描述】:

JDK 中是否有类似这样的接口:

public interface Callback<T> {
    public void process(T t);
}

要求是实现一个运行代码但不返回任何内容的回调。

我可以自己编写(只需使用此处的示例代码),但我想使用现有的轮子(如果有的话),而不是重新发明一个。

【问题讨论】:

  • 这可以很容易地解释为寻找 Java Annotation Processing API,因为:Annotation Processing API 是一种回调机制,旨在处理通用注释.但事实证明,这样的解释是错误的。我建议这个问题要么微不足道,要么具有误导性。
  • @edwardw 我对问题文本进行了改组,以使我认为已经很清楚,更清楚了。
  • 这是最容易改造的轮子。
  • @edwardw 它是如何误导的? (以及注解是如何进入的?)
  • @Dave Newton 问题中的三件事:回调 + 通用 + 过程。此外,正如你所说,我当然没有预料到这么简单的问题。所以我认为查询者不知道注释处理 API 并且正在寻找它。当然可能只有我一个人。

标签: generics interface java java-7


【解决方案1】:

所以你需要类似的东西

interface Foo<T>
    bar(T)

JDK中只有3个接口是这样的

java.nio.file.DirectoryStream$Filter<T>

    boolean accept(T entry) throws IOException;


java.lang.Comparable<T>

    int compareTo(T o);


javax.xml.ws.Provider<T>

    T invoke(T request);

显然你不会喜欢它们。

Async IO 有回调接口,不过稍微复杂一点:

java.nio.channels.CompletionHandler<V,A>

    void completed(V result, A attachment);

    void failed(Throwable exc, A attachment);

【讨论】:

  • 那你怎么知道只有3个这样的界面?如果您解析 javadocs,我会为您 +1,否则我认为您肯定不会知道
  • 通过反射所有 java/javax 类
  • 留给读者作为练习:) 基本上,对于所有 jre jar,列出条目以获取所有类,然后反映每个类。
  • 这是一个经过充分研究的答案,但你是对的 - 它们不适合。不过谢谢 (+1)
  • @MK。没有太多代码可以发布,真的。此外,还有一些库可以为您进行签名搜索,而且代码更少。
【解决方案2】:

不,我不相信目前有这样的界面。目前在 JDK 8 中计划有这样一个接口,称为 Block(我认为是 apply 方法)......尽管名称可能会在现在和那时发生变化。

【讨论】:

  • 有趣的是,在 java8 中,调用者可以使用 lambda 表达式而无需提及接口/方法;所以 Bohemian 引入自己的界面也没什么大不了的。
  • 目前是apply 方法。见here
  • @saintali: java.util.functions.Block,目前无论如何。
  • 我最终阅读了java.util.functions 中的所有课程。真的很有趣!谢谢。
【解决方案3】:

这看起来像 Guava 的 Function,除了一个函数允许返回一些东西。因此它看起来像一个

public interface Callback<T> extends Function<T, Void> {
}

不是 JDK 的一部分,但 Guava 现在非常常用,您可能会发现它很方便。

【讨论】:

    【解决方案4】:

    根据我的经验,JDK 中没有现成的这样的接口。泛型只是在 Java 游戏中出现得很晚。在此之前,需要以半类型安全的方式将几个类型化的参数传递给回调,并且无需事先了解这些参数结构(我说“半类型安全”,因为发明了事件侦听器来测试事件的类型并根据需要进行投射)。如果没有泛型,您就无法构建该机制,并且他们从未重新构建整个 JDK 以考虑泛型(集合 API 和其他一些 API 除外)。这将是一项艰巨的任务,但收效甚微(毕竟,一切都按预期工作)。

    因此,在 JDK 库中普遍存在的观察者/侦听者模式(请参阅java.util.EventObjectjava.util.EventListerner 及其用法)。在实现EventListener 时,Java 还认为在接口定义期间会更加冗长。为了更清晰的实现,该模式的专门实现应该使回调方法名称展示代码的目的(通常也与事件的名称匹配)。例如,ActionEvent#actionPerformed(ActionEvent e)

    该接口不存在的另一个可能原因是它没有在 JDK 本身中使用。有时您希望Callback&lt;T&gt; 其他人为Callback&lt;T, V&gt; 甚至Callback&lt;T, R, V&gt; 等。提供那些没有任何真实用例的接口(在JDK 内部)确实不是一个非常好的设计策略。缺乏对此类有用构造的支持是 Guava 和 Apache Commons(以及其他)存在的主要原因。

    无论如何,我同意@JB Nizet 你应该使用 Guava。我们没有具体说明您使用该界面的原因和方式,因此留下了很大的猜测空间,但无论出于何种原因,Guava 可能还有其他可能派上用场的功能。

    【讨论】:

      【解决方案5】:

      这里真正的问题是为什么?为什么您认为为此定义接口比使用 Java 提供的接口更糟糕?你会得到什么?您将失去选择合适名称的能力。我想就是这样。如果您有理由使用由 Java 库提供的现有接口,您会已经知道它的名称,因为您会知道您计划与库的哪个部分进行交互。 使用一种方法创建接口并不是重新发明轮子。

      【讨论】:

      • 两个原因:a) 我想避免类膨胀,b) 如果合适的话,应该使用那里的东西
      • 如果我阅读了您的代码并看到您使用 Java 库接口,我会错误地认为它实际上是用于与该库进行接口。
      • 所以如果我实现了Comparable 接口,这意味着我正在“与java.lang 库交互”吗? ...不,它没有,它没有。你严重错过了问题的重点。我想要像Comparable 这样一般的东西,但根据问题有一个签名。 (实际上,Comparable 是最合适的 - 请参阅不可靠的答案)
      • 好吧,如果您打算将 Comparable 用于您所描述的内容,我什至不会。
      【解决方案6】:

      在 Java 8 中,the java.util.function.Consumer class 完全符合您的要求。

      它有一个非默认方法,它接受泛型类型并且不返回任何内容:

      public interface Consumer<T> {
      
          void accept(T t);
      
          default Consumer<T> andThen(Consumer<? super T> after) {
              // ...
          }
      }        
      

      【讨论】:

        【解决方案7】:

        如果您打算应用观察者设计模式,Java 从 JDK 1.0 开始就在其标准库中支持它。您正在寻找的接口是 java.util.Observer。该模式的另一面是 java.util.Observable 类。基本上,你扩展 java.util.Observable,然后注册你的 Observers(据我了解,一个 Observer 可以同时观察多个 Observable)。这是相当古老的东西,所以要小心:没有泛型。

        【讨论】:

        • 这个答案是错误,因为Observable 没有输入,而且问题显然需要一个typed 类/接口。但是,鉴于您的声誉不佳,我不会对您投反对票 - 我将允许您删除此帖子
        • 不,您没有明确请求 generic(而不是 typed)类/接口。您要求的东西看起来“like this”,这会误导您的身份,并且您不愿意以与标准库的兼容性为代价。
        • 在java中,“typed”的意思是“有一个通用参数”。如果你阅读了这个问题,尤其是标题,它显然要求一个 generic 类(“typed”这个词不会出现在问题的任何地方)。
        【解决方案8】:

        我使用 Callable (http://docs.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/Callable.html) 在 java 中实现回调/函子。

        interface Callable<V> {
            public V call();
        }
        

        你可以使用 java.util.concurrent 中的 Executors 来处理这个。

        【讨论】:

        • 这个答案错误,因为call方法不接受类型V,而是返回 它。但是,鉴于您的声誉不佳,我不会对您投反对票 - 我将允许您删除此帖子。
        • 我认为这还是有帮助的。 +1
        • @jayunit100 它有什么帮助? call() 方法究竟是如何访问对象的?
        • 猜我误解了这个问题。我知道这不是确切的签名,但它是实现回调的一种方式。回调对象本身实现了callable;实际回调的逻辑在 call 方法的实现中。这样做可以使您的回调实现与 Java.until.concurrent.Executor 等中的调度和执行代码兼容。但是,如果您的方法完全需要上面的接口,那么正如其他人所说,您很可能需要滚动你自己。如果这对您仍然没有意义,我将删除。
        • @Bohemian 对健怡可乐有点苛刻,不是吗?天哪。
        【解决方案9】:

        称为注解处理。 JSR 269: Pluggable Annotation Processing API 定义了 API,它是 JDK 6 的一部分。您可以从 herehere 开始。

        【讨论】:

        • 嗯?您可能需要提供更多信息才能使此答案有所帮助。
        • @edwardw 到底注释处理与这个问题有什么关系?您是否有任何机会提交了错误的答案?
        • @Bohemian 哦,那我看错了你的问题。所以你已经回答了你自己的问题。首先为什么要打扰?
        • 让我详细说明。 Annotation Processing API 是一种回调机制。而且,它旨在处理通用注释。符合要求,对吧?如果是这样,我会认为您的问题微不足道或具有误导性。
        • @edwardw 如果您找到符合我的问题要求的interface(或抽象类),请在此处发布,我会接受您的回答! (告诉我一个使用回调的框架并不能真正回答我的问题)
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-08-23
        • 2018-09-15
        • 2022-12-18
        • 2020-09-16
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多