94

This may sounds like a strange question, but is there a way to refer to a standard no-op (aka null operation, null-pattern method, no-operation, do-nothing method) method for a Lambda in Java 8.

Currently, I have a method that takes a, say, void foo(Consumer<Object>), and I want to give it a no-op, I have to declare:

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

where I would like to be able to do something like:

foo(Object::null)

instead. Does something like exist?

Not sure how that would work with multi-parameter methods -- perhaps this is a deficiency in the lambdas in Java.

Ben
  • 4,785
  • 3
  • 27
  • 39
  • 5
    Related: http://stackoverflow.com/a/26553481/1441122 – Stuart Marks Apr 24 '15 at 17:51
  • 1
    "Null Object" pattern is the name of this (per Martin Fowler's Refactoring book - 1997 and updated in 2018). And yes, it'd be great if most interfaces in the JDK shipped with a public static inner class NULL or NullObject. – paul_h Dec 12 '18 at 05:58
  • 1
    I mean .. Most interfaces in the JDK should ship with a inner class that is a Null Object implementation, and a public static var NULL or NullObject which is an instance of that for all to use, like so: foo = Consumer.NULL; – paul_h Dec 12 '18 at 09:02
  • Here was as close as I could get staying in the spirit of the JDK designers: https://stackoverflow.com/a/76985309/501113 – chaotic3quilibrium Aug 27 '23 at 16:58

7 Answers7

88

This is no deficiency.

Lambdas in Java are instances of functional interfaces; which, in turn, are abstracted to instances of Java constructs which can be simplified to one single abstract method, or SAM.

But this SAM still needs to have a valid prototype. In your case, you want to have a no-op Consumer<T> which does nothing whatever the T.

It still needs to be a Consumer<T> however; which means the minimal declaration you can come up with is:

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

and use NOOP where you need to.

fge
  • 119,121
  • 33
  • 254
  • 329
42

In your particular case you could simply do:

foo(i -> {});

This means that the lambda expression receives a parameter but has no return value.

The equivalent code for a BiConsumer<T, U> would be:

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

bifoo((a, b) -> {});
Anderson Vieira
  • 8,919
  • 2
  • 37
  • 48
  • 2
    Can be extends for any number of arguments too: foo((a,b) -> {}); etc – Ben Apr 24 '15 at 16:34
  • I don't like having to introduce an faked/ignored parameter. It harms readability. I've found this preferrable: https://stackoverflow.com/a/76985309/501113 – chaotic3quilibrium Aug 27 '23 at 00:25
13

Could Function.identity() fit your needs?

Returns a function that always returns its input argument.

Neuron
  • 5,141
  • 5
  • 38
  • 59
OldCurmudgeon
  • 64,482
  • 16
  • 119
  • 213
  • 18
    Well, you can say `Consumer c=Function.identity()::apply;` but the question is whether this is really better than `c=ignore->{};`… – Holger Apr 24 '15 at 17:54
  • 2
    actually i think i like Function.identity()::apply as it doen't intriduce an unused parameter – jk. Aug 22 '16 at 17:10
  • might not have been what op was looking for, but this is what i was looking for, thanks! – logi0517 Sep 30 '19 at 14:06
  • 2
    I know this is stupid, but I just used `Function.identity()::apply; over (v)->{}` as formatter leaves it in the same line instead of hardbreaking { } XD – Antoniossss Apr 27 '22 at 09:00
  • I don't like the whole "ignored input parameter" approach. I prefer accurate and strongly typed: https://stackoverflow.com/a/76985309/501113 – chaotic3quilibrium Aug 27 '23 at 16:59
  • You can't use a `Function` as a `Consumer`. You haven't tried this. – user207421 Aug 29 '23 at 02:22
9

You can have your own NOOP implementation, similar to Function.Identity.

static <T> Consumer<T> NOOP() {
    return t -> {};
}
MNZ
  • 845
  • 7
  • 11
7

If you want a method reference for a method that does nothing, the easiest way is to write a method that does nothing. Notice that in this example I have used Main::doNothing when a Consumer<String> is required.

class Main {

    static void doNothing(Object o) { }

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

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

You could also overload doNothing by providing a version using varargs.

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

This signature will accept literally any sequence of parameters (even primitives, as these will get autoboxed). That way you could pass Main::doNothing whenever the functional interface's method has void return type. For example you could pass Main::doNothing when an ObjLongConsumer<Integer> is needed.

Paul Boddington
  • 37,127
  • 10
  • 65
  • 116
  • Can be generic for even more applicability. `static U noop(T... a) {return null;}` – Radiodef Apr 25 '15 at 06:05
  • 2
    @Radiodef I thought about mentioning that in my answer but decided I didn't like it because you can pass `noop` even in the case where the functional interface's method returns a primitive type, which is asking for a null pointer exception. – Paul Boddington Apr 25 '15 at 09:23
  • 2
    @Radiodef The other unfortunate thing is that the signatures of the versions returning `U` and `void` have the same erasure, so either the methods would have to have different names, or they'd have to be in different classes. Personally I think this *is* a deficiency, and something like `noop` or `doNothing` would fit natually in the `Objects` class. – Paul Boddington Apr 25 '15 at 09:36
  • All true. I didn't think of the unboxing problem. – Radiodef Apr 25 '15 at 09:42
5

If you want something that is very close to a no-op, you can use Objects::requireNonNull.

Using x -> {} also works of course, but your IDE's auto-formatter may try to split it up onto multiple lines.

drspa44
  • 1,041
  • 8
  • 12
0

Note: I have found this Java Lambda Shapes Reference as a Google Sheet useful.


I don't like how the Java design team omitted the notion of a VoidSupplier.

I want something that gives me a strongly typed @FunctionalInterface, where I don't have to pass an "ignored" parameter to a lambda function (a.k.a. closure) that doesn't return anything.

As a result, I created a class that fills in this obvious gap.

public class FunctionUtils {

  private FunctionUtils() {
    //Suppress instantiation
  }

  public static final VoidSupplier NO_OP = () -> {
  };

  @FunctionalInterface
  public interface VoidSupplier {

    void get();
  }
}
chaotic3quilibrium
  • 5,661
  • 8
  • 53
  • 86