Bin*_*obe 8 java equality immutability java-8 functional-interface
我不确定如何确定功能接口的相等/不变性.我想在java 8中使用这个语法糖时可能无法保证平等,如果你有任何提示,请告诉我任何提示.
我为我的问题制作了一个简短的代码片段.
public interface Element {
void doSomething(int a);
}
Run Code Online (Sandbox Code Playgroud)
我试图以功能方式添加此接口的实例
public class FunctionSet {
public void doubleUp(int a) {
System.out.println(a*2);
}
public void square(int a) {
System.out.println(a*a);
}
public static void main(String[] args) {
HashSet<Element> set = new HashSet<>();
FunctionSet functionSet = new FunctionSet();
set.add(functionSet::doubleUp);
set.add(functionSet::square);
System.out.println(set.add(functionSet::doubleUp));
}
}
Run Code Online (Sandbox Code Playgroud)
它打印为true,这意味着没有任何相等检查,并且我添加它后也无法从Set中删除任何实例.
如果我使用功能接口作为参数,有什么方法可以以某种方式比较这些实例?
将提供任何帮助,谢谢!
您可以将方法引用存储到变量中:
public static void main(String[] args) {
HashSet<Element> set = new HashSet<>();
FunctionSet functionSet = new FunctionSet();
Element fn = functionSet::doubleUp;
set.add(fn);
set.add(functionSet::square);
System.out.println(set.add(fn));
}
Run Code Online (Sandbox Code Playgroud)
这样就返回 false。
当您在不同的代码位置创建相同的 labmda 或方法引用时,与在两个位置创建新的匿名类大致相同:
public static void main(String[] args) {
HashSet<Element> set = new HashSet<>();
FunctionSet functionSet = new FunctionSet();
set.add(new Element() {
@Override
public void doSomething(int a) {
functionSet.doubleUp(a);
}
});
set.add(new Element() {
@Override
public void doSomething(int a) {
functionSet.square(a);
}
});
System.out.println(set.add(new Element() {
@Override
public void doSomething(int a) {
functionSet.doubleUp(a);
}
}));
}
Run Code Online (Sandbox Code Playgroud)
所以每次它都是不同的对象,尽管它可能看起来相同。对于每个遇到的方法引用,都会在运行时创建单独的匿名类:
Element e1 = functionSet::doubleUp;
Element e2 = functionSet::doubleUp;
System.out.println(e1.getClass());
System.out.println(e2.getClass());
Run Code Online (Sandbox Code Playgroud)
输出将是这样的:
class FunctionSet$$Lambda$1/918221580
class FunctionSet$$Lambda$2/1554547125
Run Code Online (Sandbox Code Playgroud)
所以实际上它是两个不同类的两个不同对象。如果不比较它们的字节码,就很难断定它们做了同样的事情。另请注意,它们都捕获functionSet
变量,因此还应确保它在两个方法引用之间没有更改。
我能想到的唯一解决方法是将所有方法引用声明为代码中的常量,然后引用它们,而不是直接使用方法引用:
public static final Element FN_DOUBLE_UP = new FunctionSet()::doubleUp;
public static final Element FN_SQUARE = new FunctionSet()::square;
public static void main(String[] args) {
HashSet<Element> set = new HashSet<>();
set.add(FN_DOUBLE_UP);
set.add(FN_SQUARE);
System.out.println(set.add(FN_DOUBLE_UP));
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
866 次 |
最近记录: |