我看到lambda的类是isSynthetic() && !isLocalOrAnonymousClass(),但我假设代理类也是如此。当然,我可以检查getDeclaredMethods().length == 1并将regexp应用于类名。然而,我想知道是否有一个更优雅和健壮的选项来确定给定的对象是否是lambda。
isSynthetic() && !isLocalOrAnonymousClass()
getDeclaredMethods().length == 1
regexp
qlfbtfca1#
没有官方的方法可以通过设计来做到这一点。lambda是语言的一部分;并且通过函数接口集成到类型系统中。应该没有必要区分Runnable最初是作为lambda、命名类还是内部类出现的--它们都是Runnables。如果您认为必须通过分解类文件来“处理lambda”,那么您几乎肯定做错了什么!
Runnable
abithluo2#
如果您知道lambda扩展Serializable,则可以检查生成的合成writeReplace方法是否返回SerializedLambda,如下所示。
Serializable
writeReplace
SerializedLambda
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 {} }
i86rm4rw3#
检查Runnable-或任何其他函数接口-是否已经被Lambda实现的一个简单方法是检查类是否是合成的,而接口的函数不是:
Class clz = suspectedObject.getClass(); var isLambda = clz.isSynthetic() && !clz.getDeclaredMethod("run").isSynthetic();
注意,这也会检测函数引用(this::run)--我不认为有办法区分这种形式和匿名lambda。我想使用这个方法以一种更好的方式记录对象的类型-我的框架有时记录所提供的接口实现的名称,以让用户知道他们的代码的哪一部分有问题,而lambda的toString()几乎是无用的。我并不是说我已经想出了一种有用的方式来表示“您应该查看这个特定的lambda,而不是您的类中的其他几十个lambda中的任何一个。
this::run
toString()
pkwftd7m4#
public static boolean isLambda(Object obj) { return obj.getClass().toString().contains("$$Lambda$"); }
4条答案
按热度按时间qlfbtfca1#
没有官方的方法可以通过设计来做到这一点。lambda是语言的一部分;并且通过函数接口集成到类型系统中。应该没有必要区分
Runnable
最初是作为lambda、命名类还是内部类出现的--它们都是Runnables。如果您认为必须通过分解类文件来“处理lambda”,那么您几乎肯定做错了什么!abithluo2#
如果您知道lambda扩展
Serializable
,则可以检查生成的合成writeReplace
方法是否返回SerializedLambda
,如下所示。i86rm4rw3#
检查
Runnable
-或任何其他函数接口-是否已经被Lambda实现的一个简单方法是检查类是否是合成的,而接口的函数不是:注意,这也会检测函数引用(
this::run
)--我不认为有办法区分这种形式和匿名lambda。我想使用这个方法以一种更好的方式记录对象的类型-我的框架有时记录所提供的接口实现的名称,以让用户知道他们的代码的哪一部分有问题,而lambda的
toString()
几乎是无用的。我并不是说我已经想出了一种有用的方式来表示“您应该查看这个特定的lambda,而不是您的类中的其他几十个lambda中的任何一个。pkwftd7m4#