Java中功能接口实例的相等性 [英] Equality of instance of functional interface in java

查看:82
本文介绍了Java中功能接口实例的相等性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我不确定如何确定功能接口的相等性/不变性. 我猜想在Java 8中使用这种语法糖时可能无法保证平等,请告诉我任何提示.

I am not sure how I can be sure about equality/immutability of functional interface. I guess there might be no way to assure equality when I use this syntactic sugar in java 8, please let me know any hint if you have any.

我为我的问题写了一个简短的代码段.

I made a short code snippet for my question.

public interface Element {
    void doSomething(int a);
}

并且我尝试以功能性方式添加此接口的实例

and I've tried to add instance of this interface in functional way

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));
    }

}

它显示为true,这意味着没有任何相等性检查,而且添加后我也无法从Set中删除任何实例.

it prints true which means there were not any equality check and also I can't remove any instance from Set once I add it.

如果我使用功能接口作为参数,是否可以通过某种方式比较那些实例?

in case I use functional interface as an argument, Is there any way that I can compare those instance somehow?

感谢您的帮助,谢谢!

推荐答案

您可以将方法引用存储到变量中:

You can store your method reference into a variable:

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));
}

以这种方式返回false.

This way it returns false.

在不同的代码位置创建相同的labmda或方法引用时,与在两个位置上创建新的匿名类大致相同:

When you create the same labmda or method reference in different code locations, it's roughly the same as you would create a new anonymous class in both positions:

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);
        }
    }));
}

因此,每次它都是一个不同的对象时,尽管它看起来可能是相同的.对于每个遇到的方法引用,在运行时都会创建一个单独的匿名类:

So every time it's a different object, though it may look the same. For every encountered method reference separate anonymous class is created at the runtime:

Element e1 = functionSet::doubleUp;
Element e2 = functionSet::doubleUp;

System.out.println(e1.getClass());
System.out.println(e2.getClass());

输出将如下所示:

class FunctionSet$$Lambda$1/918221580
class FunctionSet$$Lambda$2/1554547125

因此实际上是两个不同类的两个不同对象.不比较字节码就很难得出结论,他们做同样的事情.另外请注意,它们都捕获了functionSet变量,因此还应确保在两个方法引用之间未更改它.

So practically it's two distinct objects of two distinct classes. It would be quite difficult to conclude that they do the same thing without comparing their bytecode. Also note that they both capture the functionSet variable, so it should also be ensured that it wasn't changed between two method references.

我能想到的唯一解决方法是在代码中将所有方法引用声明为常量,然后再引用它们,而不是直接使用方法引用:

The only workaround I can think up is to declare all the method references as constants in your code and later reference them instead of using method references directly:

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));
}

这篇关于Java中功能接口实例的相等性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆