How to correctly determine that an object is a lambda?

后端 未结 3 1279
佛祖请我去吃肉
佛祖请我去吃肉 2020-12-14 14:38

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

Of c

相关标签:
3条回答
  • 2020-12-14 14:39

    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 {}
    }
    
    0 讨论(0)
  • 2020-12-14 14:57
    public static boolean isLambda(Object obj) {
        return obj.getClass().toString().contains("$$Lambda$");
    }
    
    0 讨论(0)
  • 2020-12-14 15:01

    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!

    0 讨论(0)
提交回复
热议问题