Lambdas are purely a call-site construct: the recipient of the lambda does not need to know that a Lambda is involved, instead it accepts an Interface with the appropriate method.

In other words, you define or use a functional interface (i.e. an interface with a single method) that accepts and returns exactly what you want.

Since Java 8 there is a set of commonly-used interface types in java.util.function.

For this specific use case there's java.util.function.IntBinaryOperator with a single int applyAsInt(int left, int right) method, so you could write your method like this:

static int method(IntBinaryOperator op){
    return op.applyAsInt(5, 10);
}

But you can just as well define your own interface and use it like this:

public interface TwoArgIntOperator {
    public int op(int a, int b);
}

//elsewhere:
static int method(TwoArgIntOperator operator) {
    return operator.op(5, 10);
}

Then call the method with a lambda as parameter:

public static void main(String[] args) {
    TwoArgIntOperator addTwoInts = (a, b) -> a + b;
    int result = method(addTwoInts);
    System.out.println("Result: " + result);
}

Using your own interface has the advantage that you can have names that more clearly indicate the intent.

Answer from Joachim Sauer on Stack Overflow
Top answer
1 of 16
337

Lambdas are purely a call-site construct: the recipient of the lambda does not need to know that a Lambda is involved, instead it accepts an Interface with the appropriate method.

In other words, you define or use a functional interface (i.e. an interface with a single method) that accepts and returns exactly what you want.

Since Java 8 there is a set of commonly-used interface types in java.util.function.

For this specific use case there's java.util.function.IntBinaryOperator with a single int applyAsInt(int left, int right) method, so you could write your method like this:

static int method(IntBinaryOperator op){
    return op.applyAsInt(5, 10);
}

But you can just as well define your own interface and use it like this:

public interface TwoArgIntOperator {
    public int op(int a, int b);
}

//elsewhere:
static int method(TwoArgIntOperator operator) {
    return operator.op(5, 10);
}

Then call the method with a lambda as parameter:

public static void main(String[] args) {
    TwoArgIntOperator addTwoInts = (a, b) -> a + b;
    int result = method(addTwoInts);
    System.out.println("Result: " + result);
}

Using your own interface has the advantage that you can have names that more clearly indicate the intent.

2 of 16
78

To use Lambda expression you need to either create your own functional interface or use Java functional interface for operation that require two integer and return as value. IntBinaryOperator

Using user defined functional interface

interface TwoArgInterface {

    public int operation(int a, int b);
}

public class MyClass {

    public static void main(String javalatte[]) {
        // this is lambda expression
        TwoArgInterface plusOperation = (a, b) -> a + b;
        System.out.println("Sum of 10,34 : " + plusOperation.operation(10, 34));

    }
}

Using Java functional interface

import java.util.function.IntBinaryOperator;

public class MyClass1 {

    static void main(String javalatte[]) {
        // this is lambda expression
        IntBinaryOperator plusOperation = (a, b) -> a + b;
        System.out.println("Sum of 10,34 : " + plusOperation.applyAsInt(10, 34));

    }
}
🌐
GeeksforGeeks
geeksforgeeks.org › java › java-lambda-expressions-parameters
Java - Lambda Expressions Parameters - GeeksforGeeks
July 23, 2025 - This method is a generic method that takes a type parameter. This interface can be implemented anywhere in a program using a lambda expression instead of creating classes with multiple functions.
🌐
Oracle
docs.oracle.com › javase › tutorial › java › javaOO › lambdaexpressions.html
Lambda Expressions (The Java™ Tutorials > Learning the Java Language > Classes and Objects)
However, when the Java runtime invokes the method printPersonsWithPredicate, it's expecting a data type of Predicate<Person>, so the lambda expression is of this type. The data type that these methods expect is called the target type. To determine the type of a lambda expression, the Java compiler uses the target type of the context or situation in which the lambda expression was found.
🌐
GitHub
gist.github.com › dgageot › bda57296107ca6a0e9df
Find Lambda parameter types · GitHub
In the example above, the name of class of lambdaInLambda is like test.FindParametersTypes$$Lambda$3/1349393271 but the corresponding method in the root class is lambda$null$1 and lambda$null$2 is actually the lambda for forEach so that the firstParameterSmart would cause a misditection. [class java.lang.String] [class java.lang.String] [interface java.util.function.Function]
🌐
Baeldung
baeldung.com › home › java › lambda expressions and functional interfaces: tips and best practices
Lambda Expressions and Functional Interfaces: Tips and Best Practices | Baeldung
December 16, 2023 - Foo foo = parameter -> { String result = "Something " + parameter; //many lines of code return result; }; It is important to note, we shouldn’t use this “one-line lambda” rule as dogma. If we have two or three lines in lambda’s definition, it may not be valuable to extract that code into another method. A compiler, in most cases, is able to resolve the type of lambda parameters with the help of type inference.
🌐
Jenkov
jenkov.com › tutorials › java › lambda-expressions.html
Java Lambda Expressions
If the lambda expression matches the parameter type (in this case the StateChangeListener interface) , then the lambda expression is turned into a function that implements the same interface as that parameter.
🌐
W3Schools
w3schools.com › java › java_lambda.asp
Java Lambda Expressions
The simplest lambda expression contains a single parameter and an expression: ... Simple expressions must return a value immediately. They cannot contain multiple statements, such as loops or if conditions. To do more complex work, use a code block with curly braces. If the lambda should return a value, use the return keyword:
🌐
DZone
dzone.com › coding › java › java lambda expressions basics
Java Lambda Expressions Basics
April 13, 2013 - In languages that support first class functions, the type of the lambda expression would be a function; but in Java, the lambda expressions are represented as objects, and so they must be bound to a particular object type known as a functional interface. This is called the target type. Since a functional interface can only have a single abstract method, the types of the lambda expression parameters must correspond to the parameters in that method, and the type of the lambda body must correspond to the return type of this method.
Find elsewhere
🌐
Netjstech
netjstech.com › 2015 › 06 › lambda-expression-as-method-parameter-java-8.html
Java Lambda Expression as Method Parameter | Tech Tutorials
December 22, 2020 - Lambda expression in Java as a method parameter. To pass a lambda expression as method argument the type of the parameter, which receives the lambda expression as an argument, must be of functional interface type.
🌐
Oracle
oracle.com › java › technical details
Java 8: Lambdas, Part 1
... The Something interface is every bit as legal and legitimate a functional interface as Runnable or Comparator<T>; we’ll look at it again after getting some lambda syntax under our belt. Syntax. A lambda in Java essentially consists of three parts: a parenthesized set of parameters, an arrow, ...
Top answer
1 of 2
14

This is currently possible to solve but only in a pretty hackie way, but let me first explain a few things:

When you write a lambda, the compiler inserts a dynamic invoke instruction pointing to the LambdaMetafactory and a private static synthetic method with the body of the lambda. The synthetic method and the method handle in the constant pool both contain the generic type (if the lambda uses the type or is explicit as in your examples).

Now at runtime the LambdaMetaFactory is called and a class is generated using ASM that implements the functional interface and the body of the method then calls the private static method with any arguments passed. It is then injected into the original class using Unsafe.defineAnonymousClass (see John Rose post) so it can access the private members etc.

Unfortunately the generated Class does not store the generic signatures (it could) so you can't use the usual reflection methods that allow you to get around erasure

For a normal Class you could inspect the bytecode using Class.getResource(ClassName + ".class") but for anonymous classes defined using Unsafe you are out of luck. However you can make the LambdaMetaFactory dump them out with the JVM argument:

java -Djdk.internal.lambda.dumpProxyClasses=/some/folder

By looking at the dumped class file (using javap -p -s -v), one can see that it does indeed call the static method. But the problem remains how to get the bytecode from within Java itself.

This unfortunately is where it gets hackie:

Using reflection we can call Class.getConstantPool and then access the MethodRefInfo to get the type descriptors. We can then use ASM to parse this and return the argument types. Putting it all together:

Method getConstantPool = Class.class.getDeclaredMethod("getConstantPool");
getConstantPool.setAccessible(true);
ConstantPool constantPool = (ConstantPool) getConstantPool.invoke(lambda.getClass());
String[] methodRefInfo = constantPool.getMemberRefInfoAt(constantPool.size() - 2);

int argumentIndex = 0;
String argumentType = jdk.internal.org.objectweb.asm.Type.getArgumentTypes(methodRef[2])[argumentIndex].getClassName();
Class<?> type = (Class<?>) Class.forName(argumentType);

UPDATED with Jonathan's suggestion

Now ideally the classes generated by LambdaMetaFactory should store the generic type signatures (I might see if I can submit a patch to the OpenJDK) but currently this is the best we can do. The code above has the following problems:

  • It uses undocumented methods and classes
  • It is extremely vulnerable to code changes in the JDK
  • It doesn't preserve the generic types, so if you pass List<String> into a lambda it will come out as List
2 of 2
1

Use a TypeRef to wrap the lambda expression.

@FunctionalInterface
interface TypeRef<T> {
    T create();

    default Class<?> getGenericType() {
        return create().getClass();
    }
}

public class Main {
    public static void main(String[] args) {
        System.out.println(getFactoryTypeParameter(() -> "hello"));
    }

    private static <T> Class<?> getFactoryTypeParameter(TypeRef<T> typeRef) {
        return typeRef.getGenericType();
    }
}

output:

class java.lang.String
🌐
TutorialsPoint
tutorialspoint.com › how-to-pass-a-lambda-expression-as-a-method-parameter-in-java
How to pass a lambda expression as a method parameter in Java?
A lambda expression is an anonymous ... a lambda expression as a method parameter in java, the type of method parameter that receives must be of functional interface type....
🌐
Rice
clear.rice.edu › comp310 › JavaResources › lambdas.html
Lambda Functions
Lambda functions in Java assume that there is a "functional" interface defined somewhere. A "functional interface" is simply an interface that defines a single method. This associated interface is related to the lambda function only in that it is the "target" type to which the lambda is being assigned, either by variable assignment or by passing the lambda as an input parameter or output parameter of a method which is typed to that interface.
🌐
Readthedocs
java-8-tips.readthedocs.io › en › stable › lambdas.html
3. Lambdas — Java 8 tips 1.0 documentation
Lambdas give us the ability to encapsulate a single unit of code block and pass on to another code. It can also be considered as anonymous function which doesn’t have any function name but has list of parameters, function body, returns result and even throws exceptions.
🌐
Developer.com
developer.com › dzone › coding › languages › java lambda: method reference
Working with Lambda Expressions in Java
December 21, 2021 - In this case, instead of using a specific object, you can use the name of the class. Therefore, the first parameter of the functional interface matches the invoking object. This is why we call it the parameter method reference.
🌐
JetBrains
jetbrains.com › help › inspectopedia › LambdaParameterTypeCanBeSpecified.html
Lambda parameter type can be specified | Inspectopedia Documentation
1 month ago - Reports lambda parameters that do not have their type specified and suggests adding the missing type declarations. ... Can be used to locate inspection in e.g. Qodana configuration files, where you can quickly enable or disable it, or adjust its settings. ... Path to the inspection settings via IntelliJ Platform IDE Settings dialog, when you need to adjust inspection settings directly from your IDE. Settings or Preferences | Editor | Inspections | Java ...
🌐
GeeksforGeeks
geeksforgeeks.org › java › lambda-expressions-java-8
Java Lambda Expressions - GeeksforGeeks
This is a zero-parameter lambda expression! ... It is not mandatory to use parentheses if the type of that variable can be inferred from the context. Parentheses are optional if the compiler can infer the parameter type from the functional interface. ... import java.util.ArrayList; public class GFG{ public static void main(String[] args){ ArrayList<Integer> list = new ArrayList<>(); list.add(1); list.add(2); list.add(3); System.out.println("All elements:"); list.forEach(n -> System.out.println(n)); System.out.println("Even elements:"); list.forEach(n -> { if (n % 2 == 0) System.out.println(n); }); } }
Published   2 weeks ago
🌐
Baeldung
baeldung.com › home › java › java local variable syntax for lambda parameters
Java Local Variable Syntax for Lambda Parameters | Baeldung
January 8, 2024 - The local variable syntax for lambda parameters is the only language feature introduced in Java 11. In this tutorial, we’ll explore and use this new feature. One of the key features introduced in Java 10 was local variable type inference. It allowed the use of var as the type of the local variable instead of the actual type.
🌐
javathinking
javathinking.com › blog › how-do-i-define-a-method-which-takes-a-lambda-as-a-parameter-in-java-8
How to Define a Method That Takes a Lambda as a Parameter in Java 8: Syntax Explained — javathinking.com
Lambdas in Java are not standalone entities—they are shorthand for implementing the single abstract method (SAM) of a functional interface. A functional interface is an interface with exactly one abstract method (SAM). This single method defines the "shape" of the lambda expression, dictating the number of parameters, their types, and the return type (if any).