我想写一个通用的dto更新程序,更新它的一些属性。我的对象如下所示:
class Person {
String firsName;
String lastName;
Integer age;
setter/getter
}
我有一个枚举,它定义了哪些字段可以被覆盖:
enum OverriddenType {
FIRST_NAME,
LAST_NAME,
AGE
}
而不是像这样做一个“硬编码”设置器。。。
public void override(Person person, Map<OverriddenType,Object> newValuesForProperties) {
newValuesForProperties.forEach((type,value)) -> {
if(type == OverriddenType.FIRST_NAME) {
person.setFirstName((String)value);
} else if(type == OverriddenType.LAST_NAME) {
person.setLastName((String)value);
} else if(type == OverriddenType.AGE) {
person.setAge((Integer)value);
}
});
}
... 我想使用一些Java8函数/使用者特性来定义每个枚举中的setter。我试过这样的方法:
enum OverriddenType {
FIRST_NAME(p -> p.setFirstName(???????)), //don't know what to set here since the value is not here
LAST_NAME(p -> p.setLastName(???????)),
AGE(p -> p.setAge(???????));
Consumer<Person> consumer;
OverriddenType(Consumer<Person> consumer) {
this.consumer = consumer;
}
public Consumer<Person> getConsumer();
}
但正如你所看到的,我不能在这里传递动态值。我也不知道逻辑会是什么样子,但我会想象这样的情况:
public void override(Person person, Map<OverriddenType,Object> newValuesForProperties) {
newValuesForProperties.forEach((type,value)) ->
type.getConsumer().accept(person, value) // this doesn't exist, but I can imagine some additional parameter passing
);
}
你能给我一个解决办法吗?它能工作吗?我担心传入的值是动态的,因此它对枚举不起作用。。
3条答案
按热度按时间41zrol4v1#
setter方法是
BiConsumer<T,U>
,在哪里T
是对象示例,并且U
是值。vm0i2vca2#
根据定义a
Consumer
只接受一个论点。由于需要同时传递要操纵的对象和新值,因此必须使用允许传递两个参数的接口。幸运的是有
BiConsumer
接口。请注意,这里使用方法引用大致相当于编写
(p, fn) -> p.setFirstName(fn)
.但是,这会带来一个小问题,因为您需要知道(并指定)参数的类型,并且您的枚举希望具有混合类型(前两种类型将返回
BiConsumer<Person,String>
最后一个可能BiConsumer<Person,Integer>
.ruyhziif3#
你需要一个
BiConsumer
它可以使用目标对象和新值:(如果您的setter接受
Object
,甚至可以使用方法引用:)
与其直接暴露消费者,不如考虑定义一个公共
assign
或者set
方法并使使用者对外不可见(信息隐藏):然后打电话给
FIRST_NAME.assign(person, "new name")
.