是否有可用于任何lambda的no-op(NOP)的方法参考?


74

这听起来像是一个奇怪的问题,但是有一种方法可以引用Java 8中Lambda的标准no-op(aka空操作,空模式方法,无操作,无操作方法)方法。

目前,我有一个方法,需要一个,void foo(Consumer<Object>)并且想要不执行任何操作,我必须声明:

foo(new Consumer<Object>() { 
  public void accept(Object o) { 
    // do nothing 
  }
}

我希望能够执行以下操作:

foo(Object::null)

代替。是否存在类似的东西?

不确定如何使用多参数方法-也许这是Java中lambda的缺陷。



“空对象”模式就是这种名称(根据Martin Fowler的Refactoring book-1997,并于2018年更新)。是的,如果JDK中的大多数接口都附带了公共静态内部类NULL或NullObject,那就太好了。
paul_h

我的意思是.. JDK中的大多数接口都应该附带一个内部类,它是一个Null Object实现,以及一个公共静态var NULL或NullObject,它是所有实例的实例,例如:foo = Consumer.NULL;
paul_h

Answers:


57

这不是缺陷。

Java中的Lambda是功能接口的实例。依次将其抽象为Java构造的实例,这些实例可以简化为一个单一的抽象方法或SAM。

但是此SAM仍需要具有有效的原型。在您的情况下,您希望没有操作Consumer<T>,而该操作什么也不做T

Consumer<T>然而,它仍然需要成为一个。这意味着您可以提出的最小声明是:

private static final Consumer<Object> NOOP = whatever -> {};

NOOP在需要的地方使用。


3
在Consumer接口本身中具有此功能将非常好。
xorcus

33

在您的特定情况下,您可以简单地执行以下操作:

foo(i -> {});

这意味着lambda表达式接收参数,但没有返回值。

的等效代码为BiConsumer<T, U>

void bifoo(BiConsumer<Object, Object> consumer) { ... }

bifoo((a, b) -> {});

2
也可以扩展为任意数量的参数:foo((a,b)-> {}); 等等
2015年

11

Function.identity()满足您的需求?

返回始终返回其输入参数的函数。


16
好吧,您可以说,Consumer<ArbitraryType> c=Function.identity()::apply;但是问题是,这是否真的比c=ignore->{};……更好
Holger 2015年

2
实际上,我认为我喜欢Function.identity():: apply,因为它不会引入未使用的参数
jk。

可能不是op正在寻找的东西,但这就是我正在寻找的东西,谢谢!
佐尔坦阿姆洛夫

7

如果要为不执行任何操作的方法提供方法参考,最简单的方法是编写不执行任何操作的方法。请注意,在此示例中,我Main::doNothingConsumer<String>需要a时使用过。

class Main {

    static void doNothing(Object o) { }

    static void foo(Consumer<String> c) { }

    public static void main(String[] args) {
        foo(Main::doNothing);
    }
}

您也可以doNothing通过使用varargs提供版本来重载。

static void doNothing(Object... o) { }

此签名实际上可以接受任何参数序列(甚至是原语,因为它们会自动装箱)。这样,Main::doNothing只要功能接口的方法具有void返回类型,就可以通过。例如,您可以Main::doNothingObjLongConsumer<Integer>需要时通过。


可以通用以获得更大的适用性。static <T, U> U noop(T... a) {return null;}
Radiodef'Apr

2
@Radiodef我想在我的答案中提到这一点,但我决定不喜欢它,因为noop即使在功能接口的方法返回原始类型(要求空指针异常)的情况下,您也可以通过。
Paul Boddington 2015年

2
@Radiodef另一个不幸的是,版本的签名返回U并且void具有相同的擦除,因此方法必须具有不同的名称,或者它们必须位于不同的类中。就我个人而言,我认为这一个缺陷,在课堂上自然noop或类似。doNothingObjects
保罗·波丁顿

都没错 我没有想到拆箱问题。
Radiodef 2015年

4

您可以拥有自己的NOOP实现,类似于Function.Identity。

static <T> Consumer<T> NOOP() {
    return t -> {};
}

1

如果您想要的东西非常接近无操作并且您已经在类路径上添加了Guava,则可以使用Preconditions::checkNotNull

使用x -> {}当然也可以,但是您IDE的自动格式化程序可能会尝试将其拆分为多行。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.