是否有一种类型可以保存java类的所有可能的setter引用,而不管所设置的类型是什么?

是否有一种类型可以保存java类的所有可能的setter引用,而不管所设置的类型是什么?,java,generics,lambda,Java,Generics,Lambda,假设我们有一个非常简单的类: public class User { private Long id; private String name; public void setId(Long id) { this.id = id; } public void setName(String name) { this.name = name; } } 我正在做一个简单的活页夹类来填充一个用户,并希望发出所需属性

假设我们有一个非常简单的类:

public class User {

    private Long id;
    private String name;

    public void setId(Long id) {
        this.id = id;
    }

    public void setName(String name) {
        this.name = name;
    }

}
我正在做一个简单的活页夹类来填充一个用户,并希望发出所需属性的信号

UserBinder binder = new UserBinder(user)
    .requires(User::setId)
    .requires(User::setName);
上述情况表明这两种属性都是必需的。当然,我可以传递值
“id”
“name”
,而不是方法引用。但似乎传递setter是非常合适的,因为需要在活页夹内部调用setter

以下几点效果很好:

public void requires(BiConsumer<User, Long> r) // for User::setId;
public void requires(BiConsumer<User, String> r) // for User::setName;
public void requires(BiConsumer)//for User::setId;
public void requires(BiConsumer)//用于User::setName;
但以下几点失败了:

public void requires(BiConsumer<User, ?> r)
public void requires(双消费者)

是否有一个类型可以保存java类的所有可能的setter引用,而不管设置的是什么类型?

您可以向
requires
方法添加一个泛型参数:

public <T> void requires(BiConsumer<User, T> consumer)
汇编得很好


您说过需要将收到的消费者存储在某个集合中,并检查该集合是否已包含一些
消费者

不幸的是,你不能轻易地做到这一点(见此)


作为一种解决方法,您可以使用与
BiConsumer
中相同的方法签名创建扩展
Serializable
@functional接口,并比较序列化字节。看见但请记住,您不能依赖此行为

您可以使用以下方法绑定类型:

<T> void requires(BiConsumer<User, T> r) {
}

要确保对象的实例化必须具有这些属性。

做到了这一点。但如果我想跟踪存储在一个集合中的消费者,该怎么办?该集合必须具有
set
的签名,但随后检查
set。contains(User::setId)
不可编译。@RicardoMarimon您可以使用签名
set
,但在您的情况下似乎没有帮助,因为比较lambda并不容易(请参见此)。最近我在考虑同样的设计,但不幸的是,它似乎不是那么容易实现。也许你可以考虑和你的活页夹一起使用?或者您可以在
Binder
上详细说明您的要求,以便我可以提出其他建议?谢谢您对问题的参考。我的印象是,你可以比较兰博达斯,从我读到的,没有保证。也许在我使用的方法引用的情况下。我将进一步探索,因为我让它与
public boolean isRequired(BiConsumer consumer){return requires.contains(consumer);}
一起使用
Set
@RicardoMarimon
Set.contains(User::setId)
不编译,但
Set.contains((BiConsumer)User::setId)
编译得很好:这可能是不可能的。您不能假设一个
双消费者
与另一个消费者相等,即使两者完全相等。你不能把它们放在一个集合中,你不能对它们进行
=
,你不能对它们进行反思,看看它们代表了什么方法。这是一个好主意,但你几乎肯定不能让它工作——更糟糕的是,它可能看起来工作,但实际上不工作。
<T> void requires(BiConsumer<User, T> r) {
}
public User(Long id, String name)