【问题标题】:Are Java method references stable? [duplicate]Java 方法引用稳定吗? [复制]
【发布时间】:2018-11-17 19:12:11
【问题描述】:

如果我使用新语法获得方法引用:

anObject::aMethod

我总是得到同一个对象吗?也就是说,我可以相信对同一方法的两个引用是相等的吗?

很高兴知道,例如,我是否计划将它们用作我可以添加和删除的 Runnable 回调:

someLibrary.addCallback(anObject::aMethod)
// later
someLibrary.removeCallback(sameObject::sameMethod)

这是否需要将引用保存在 Runnable 变量中以保持稳定?

【问题讨论】:

标签: java java-8


【解决方案1】:

JLS makes no promises 关于您从方法引用表达式中获得的身份或相等性。

您可以运行一个快速测试:

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      

但这当然取决于实现。

可以制作您的 lambda Serializable 并使用序列化表示来键入您的回调映射。见How to serialize a lambda?。虽然这会起作用,但并不完全符合规范要求。

【讨论】:

    【解决方案2】:

    试试这个就能得到答案:

    Object object = ...;
    Supplier<String> s1 = object::toString;
    Supplier<String> s2 = object::toString;
    System.out.println(s1.equals(s2));
    

    答案是……很遗憾不是。

    当然,如果您保留相同的引用(即相同的对象),它会起作用;但是,如果像上面的示例一样,您请求两个 lambda,尽管它们看起来相同,但它们永远不会相等。 因此 reference = object::method 和之后的 remove(reference) 显然会起作用,但如果集合中的 remove(sameObject::sameMethod) 是这样写的,则永远不会起作用。

    对于构造函数(例如 ArrayList::new)和未绑定的方法(例如 Object::toString),答案也是否定的。似乎每次使用 lambda 表达式都会构造一个新的 lambda。

    正如@Hitobat 指出的那样,如果您考虑一下 lambda 究竟是什么以及它们来自哪里,这种不等式是有道理的。基本上,Supplier&lt;String&gt; x = myObject::toStringSupplier&lt;String&gt; x = new Supplier&lt;String&gt;( ... ) 的语法糖。如果没有适当的 Object.equals 重载,匿名类的两个实例显然是不同的。可能和很多人一样,我认为在某处有一种经常使用的 lambda 缓存以提高效率;好吧,一点也不。

    【讨论】:

    • 我想这回想起来是有道理的。如果您认为方法引用只是更长的匿名类“new Supplier() { ... }”的语法糖,那么如果不重载Object.equals,这些匿名实例将不匹配。
    • 确切。我会在我的答案中添加一个精确的答案。
    • 正如Does a lambda expression create an object on the heap every time it's executed? 中所解释的,该规范允许对象重用,并且在某些情况下确实已经发生(即非捕获 lambda),但完全由 JVM 自行决定。由于 JVM 实现还具有 Escape Analysis,它可以透明地忽略对象创建(即 supplier1 == supplier2 被常量 false 替换,但对象甚至可能不存在),这是合理的。性能很重要,而不是x == y的结果...
    猜你喜欢
    • 1970-01-01
    • 2018-07-01
    • 2023-04-02
    • 1970-01-01
    • 2012-05-07
    • 2014-03-29
    • 2015-04-12
    • 2010-10-17
    • 2020-10-05
    相关资源
    最近更新 更多