How to correctly determine that an object is a lambda?

JavaLambdaJava 8

Java Problem Overview


I see that the class of a lambda is isSynthetic() && !isLocalOrAnonymousClass(), but I presume that the same may be true for proxy classes.

Of course, I could check that getDeclaredMethods().length == 1 and apply regexp to the class name.

However I want to know if there is a more elegant and robust option to find out if a given object is a lambda.

Java Solutions


Solution 1 - Java

There is no official way to do this, by design. Lambdas are part of the language; and are integrated into the type system through functional interfaces. There should be no need to distinguish a Runnable that began life as a lambda, a named class, or an inner class -- they're all Runnables. If you think you have to "deal with lambda" by taking apart the class file, you're almost certainly doing something wrong!

Solution 2 - Java

If you know the lambda extends Serializable you could check the synthetic writeReplace method that is generated returns a SerializedLambda as shown below.

import java.io.Serializable;
import java.lang.invoke.SerializedLambda;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.function.Function;

public class IsLambdaExample
{
    public static void main( String[] args )
    {
        System.out.println(
            "Is anonymous inner class a lambda: "+isLambda(
                new SerialisableFunction<Object,Object>(){ public Object apply( Object o ){ return null; } }
            )
        );
        System.out.println( "Is lambda a lambda: "+isLambda( (SerialisableFunction<Object,Object>)o -> null ) );
        System.out.println(
            "Is proxy instance a lambda: "+isLambda(
                (SerialisableFunction)Proxy.newProxyInstance(
                    ClassLoader.getSystemClassLoader(),
                    new Class[]{ SerialisableFunction.class },
                    new InvocationHandler()
                    {
                        @Override
                        public Object invoke( Object proxy, Method method, Object[] args )
                        {
                            return null;
                        }

                        private SerializedLambda writeReplace()
                        {
                            return new SerializedLambda( InvocationHandler.class, "", "", "", 0, "", "", "", "", new Object[]{} );
                        }
                    }
                )
            )
        );
    }

    public static <T extends Function<?,?> & Serializable> Boolean isLambda( T potentialLambda )
    {
        try{
            Class<?> potentialLambdaClass = potentialLambda.getClass();
            if( !potentialLambdaClass.isSynthetic() ){
                return false;
            }
            Method writeReplace = potentialLambdaClass.getDeclaredMethod("writeReplace");
            writeReplace.setAccessible(true);
            Object writeReplaceObject = writeReplace.invoke(potentialLambda);
            return writeReplaceObject != null && SerializedLambda.class.isAssignableFrom( writeReplaceObject.getClass() );
        }
        catch( NoSuchMethodException | IllegalAccessException | InvocationTargetException ignored ){
            return false;
        }
    }

    interface SerialisableFunction<T,U> extends Function<T,U>, Serializable {}
}

Solution 3 - Java

public static boolean isLambda(Object obj) {
    return obj.getClass().toString().contains("$$Lambda$");
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionArtem BilanView Question on Stackoverflow
Solution 1 - JavaBrian GoetzView Answer on Stackoverflow
Solution 2 - Javauser2219808View Answer on Stackoverflow
Solution 3 - JavaAlex AbrahamView Answer on Stackoverflow