【发布时间】:2014-07-28 13:16:10
【问题描述】:
假设我有一个使用 lambda 表达式(闭包)定义的对象列表。有没有办法检查它们以便进行比较?
我最感兴趣的代码是
List<Strategy> strategies = getStrategies();
Strategy a = (Strategy) this::a;
if (strategies.contains(a)) { // ...
完整代码是
import java.util.Arrays;
import java.util.List;
public class ClosureEqualsMain {
interface Strategy {
void invoke(/*args*/);
default boolean equals(Object o) { // doesn't compile
return Closures.equals(this, o);
}
}
public void a() { }
public void b() { }
public void c() { }
public List<Strategy> getStrategies() {
return Arrays.asList(this::a, this::b, this::c);
}
private void testStrategies() {
List<Strategy> strategies = getStrategies();
System.out.println(strategies);
Strategy a = (Strategy) this::a;
// prints false
System.out.println("strategies.contains(this::a) is " + strategies.contains(a));
}
public static void main(String... ignored) {
new ClosureEqualsMain().testStrategies();
}
enum Closures {;
public static <Closure> boolean equals(Closure c1, Closure c2) {
// This doesn't compare the contents
// like others immutables e.g. String
return c1.equals(c2);
}
public static <Closure> int hashCode(Closure c) {
return // a hashCode which can detect duplicates for a Set<Strategy>
}
public static <Closure> String asString(Closure c) {
return // something better than Object.toString();
}
}
public String toString() {
return "my-ClosureEqualsMain";
}
}
似乎唯一的解决方案是将每个 lambda 定义为一个字段并仅使用这些字段。如果你想打印出调用的方法,你最好使用Method。有没有更好的 lambda 表达式方法?
另外,是否可以打印 lambda 并获得人类可读的内容?如果您打印this::a 而不是
ClosureEqualsMain$$Lambda$1/821270929@3f99bd52
得到类似的东西
ClosureEqualsMain.a()
甚至使用this.toString和方法。
my-ClosureEqualsMain.a();
【问题讨论】:
-
您可以在闭包中定义toString、equals和hashhCode方法。
-
@AnkitZalani 你能举一个编译的例子吗?
-
@PeterLawrey,由于
toString是在Object上定义的,我认为您可以定义一个接口,提供toString的默认实现而不违反单一方法 接口功能的要求。不过我还没有检查过。 -
@MikeSamuel 这是不正确的。类不继承接口中声明的默认 Object 方法;请参阅stackoverflow.com/questions/24016962/… 了解说明。
-
@BrianGoetz,感谢您的指点。