如果我使用新语法获取方法引用:
anObject::aMethod
Run Code Online (Sandbox Code Playgroud)
我总是得到同一个对象吗?也就是说,我可以相信对同一方法的两个引用是相同的吗?
例如,我很乐意知道是否计划将它们用作Runnable我可以添加和删除的回调:
someLibrary.addCallback(anObject::aMethod)
// later
someLibrary.removeCallback(sameObject::sameMethod)
Run Code Online (Sandbox Code Playgroud)
这是否需要在Runnable变量中保存引用以保持其稳定?
Mis*_*sha 17
JLS 对于从方法引用表达式中获取的内容的身份或相等性没有任何承诺.
你可以运行一个快速测试:
Object obj = new Object();
IntSupplier foo = obj::hashCode;
IntSupplier bar = obj::hashCode;
System.out.println(foo == bar); // false
System.out.println(foo.equals(bar)); // false
Run Code Online (Sandbox Code Playgroud)
但这当然取决于实现.
您可以创建lambda Serializable并使用serlialized表示键回调回调映射.请参见如何序列化lambda?.虽然这可行,但并不是完全需要按规格工作.
试试这个来得到答案:
Object object = ...;
Supplier<String> s1 = object::toString;
Supplier<String> s2 = object::toString;
System.out.println(s1.equals(s2));
Run Code Online (Sandbox Code Playgroud)
答案是......不幸的是没有.
当然,如果你保持相同的参考(即同一个对象),它将起作用; 但是,如果像上面的例子那样,你要求两个lambdas,虽然它们似乎是相同的,但它们永远不会相等.因此reference = object::method,后来remove(reference)显然会起作用,但remove(sameObject::sameMethod)如果它是文字书面的话,从集合中将永远不会起作用.
对于构造函数(例如ArrayList :: new)和未绑定方法(例如Object :: toString),答案也是否定的.似乎每次使用lambda表达式时都会构造一个新的lambda.
正如@Hitobat指出的那样,如果你想一下lambda究竟是什么以及它们来自哪里,这种不平等是有道理的.Supplier<String> x = myObject::toString基本上,是一种语法糖Supplier<String> x = new Supplier<String>( ... ).如果没有正确的Object.equals重载,匿名类的两个实例显然是不同的.可能和很多人一样,我觉得在某个地方有一种经常使用的lambdas缓存可以提高效率; 好吧,一点也不.
| 归档时间: |
|
| 查看次数: |
1308 次 |
| 最近记录: |