Is there a method reference for a no-op (NOP) that can be used for anything lambda?
Asked Answered
N

7

96

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.

Nub answered 24/4, 2015 at 15:28 Comment(4)
Related: https://mcmap.net/q/94737/-built-in-java-8-predicate-that-always-returns-trueMcclary
"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.Exhort
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;Exhort
Here was as close as I could get staying in the spirit of the JDK designers: https://mcmap.net/q/94021/-is-there-a-method-reference-for-a-no-op-nop-that-can-be-used-for-anything-lambdaRestrainer
C
89

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.

Crossfade answered 24/4, 2015 at 15:39 Comment(2)
Would be really nice to have this in the Consumer interface itself.Halyard
Or, perhaps they could offer a strongly typed solution, like this: https://mcmap.net/q/94021/-is-there-a-method-reference-for-a-no-op-nop-that-can-be-used-for-anything-lambdaRestrainer
B
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) -> {});
Billibilliard answered 24/4, 2015 at 15:42 Comment(2)
Can be extends for any number of arguments too: foo((a,b) -> {}); etcNub
I don't like having to introduce an faked/ignored parameter. It harms readability. I've found this preferrable: https://mcmap.net/q/94021/-is-there-a-method-reference-for-a-no-op-nop-that-can-be-used-for-anything-lambdaRestrainer
P
12

Could Function.identity() fit your needs?

Returns a function that always returns its input argument.

Pacesetter answered 24/4, 2015 at 15:48 Comment(6)
Well, you can say Consumer<ArbitraryType> c=Function.identity()::apply; but the question is whether this is really better than c=ignore->{};Jaguarundi
actually i think i like Function.identity()::apply as it doen't intriduce an unused parameterHaletta
might not have been what op was looking for, but this is what i was looking for, thanks!Frag
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 { } XDCatullus
I don't like the whole "ignored input parameter" approach. I prefer accurate and strongly typed: https://mcmap.net/q/94021/-is-there-a-method-reference-for-a-no-op-nop-that-can-be-used-for-anything-lambdaRestrainer
You can't use a Function as a Consumer. You haven't tried this.Megohm
S
10

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

static <T> Consumer<T> NOOP() {
    return t -> {};
}
Samul answered 9/8, 2017 at 20:0 Comment(0)
I
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.

Incredulous answered 24/4, 2015 at 15:55 Comment(4)
Can be generic for even more applicability. static <T, U> U noop(T... a) {return null;}Majolica
@Majolica 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.Incredulous
@Majolica 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.Incredulous
All true. I didn't think of the unboxing problem.Majolica
O
6

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.

Ora answered 20/10, 2020 at 15:16 Comment(1)
IDE's auto-formatter may try to split it up onto multiple lines <-- This is why I came here searching for a solution :-)Latona
R
1

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();
  }
}
Restrainer answered 27/8, 2023 at 0:23 Comment(2)
Why not use java.lang.Runnable? It even has the @FunctionalInterface Annotation.Backwards
The Runnable interface is terrible in terms of readability. Almost all source code is read at least an order of magnitude more than written. Therefore, reducing the time it takes for a future someone (including myself 6 months later) to read through code and understand its implications quickly is of vital importance. The Runnable interface forces the reader to slow down and try to figure out the concurrency/multi-threaded implications of its use. Whereas VoidSupplier is explicit in what it offers with no concurrency ambiguities.Restrainer

© 2022 - 2024 — McMap. All rights reserved.