Java In A Nutshell— Function Interfaces, Lambdas and Method References

Alexanderkilroy
3 min readApr 4, 2021

Introduction

Lambdas bring a degree of simplicity to Java. Rather than being explicitly verbose at every corner, what if we could pass a functional expression similar to those find in other languages, such as JavaScript:

let n = (param1) => someOperation(param1);
n();

Fortunately Java introduced this in Java 8 but it isn’t identical, we’ll look at making our own lambda in Java and cover the steps to do so.

Creating a Function Interface

Firstly, Java is static and therefore cannot magically infer some dynamic type to run against for a lambda. Instead, they’ve provided us interfaces which can be lambda[ised]:

Utilising a Lambda

Now we just need to utilise our functional interface:

We create the variable to store our expression within, a.k.a., our lambda method reference and pass it a lambda implementation which is compliant with our single public abstract method signature. This one utilises generics, but there’s nothing stopping you hard-coding types either.

After which we use the reference to call the interface member, which uses our lambda implementation and computes our operation with our given operand.

What about scoping though?

In the above example, I’ve commented out modification. This is because any member variable accessed from the local method’s scope must be final or effectively final, i.e., it cannot be called for modification.

Fortunately, we can use field members:

So lambdas are just method declaration and implementation references?

Yup, by this logic, a functional interface only needs a reference to an implementation, and a lambda is just an implementation. Java 8 provides method references:

// :: denotes we're referencing a method
FunctionInterfaceStaticType name = Class::methodName;

And we can use one to access and fulfil our functional interface compliance too!

Consider the following:

Could be refactored to:

Note: The actual method name for this implementation doesn’t matter at all, could be named bobsburgers for all the JVM cares

Now this doesn’t only work for static members, but instance too:

That’s pretty much it honestly. But, wouldn’t it be great if we didn’t have to keep making functional interfaces every single time we want a lambda or reference for personal use and not part of some library?

Built in Functional Interfaces

Welp, Java has many built in functional interfaces already. Here’s a summary of each:

Predicates

A predicate takes a single argument and returns a boolean:

Logical AND

Now on the actual functional interface itself, it has some cool methods for us to chain predicates together, such as logical and:

Logical NOT

We can negate the value too:

Logical OR

We can present another predicate, and if it logically returns true, so does the final result:

Functions

Functions Functional Interface takes a single argument and returns a result of type T:

andThen

We can chain functions together using the value from the previous function:

Suppliers

A supplier returns a value:

Consumers

A consumer consumes a parameter and returns nothing:

andThen

Consumers can also perform an andThen with another consumer:

Comparators

Takes a single type argument and compares two given objects, returning an integer for the result:

Comparators have pretty wide range of utility functions which can be executed subsequently, I’d going to have to suggest the API for this: API Doc

Additional Function Interfaces

Bi Functional Interfaces

Any interface prefixed with Bi implies it takes two arguments, so, for example:

Function<Param Type, Return Type>
BiFunction<Param t1, Param t2, return t>

Working with Primitives

Functional Interfaces cannot accept primitives as their generic natively, to combat this issue, there are many, many built in primitive oriented function interfaces such as:

  1. DoubleFunction
  2. LongFunction
  3. IntFunction

As you can imagine, all primitive types are supported and their work identical to their reference oriented counter parts.

Additionally we have the ‘To<Type>Bi<Function type>’ Functional interfaces, to allow us to accept two arguments and return a single primitive, akin to their reference type Bi counter parts.

Final

And that concludes the Lambdas and method references article. You can reach me in my discord server.

Ciao!

--

--

Alexanderkilroy

I'm just a self taught developer from England, honestly, that's it lol.