Java class 方法以 Class 和 Field 作为参数
Java class method with Class and Field as parameters
如何创建接受 Class 和 Field 作为参数的方法?像这样:
List<SomeClassEntity> list = ...;
// Service to make useful things around a list of objects
UsefulThingsService<SomeClassEntity> usefulThingsService = new UsefulThingsService<>();
// Maybe invoke like this. Did't work
usefulThingsService.makeUsefulThings(list, SomeClassEntity.class, SomeClassEntity::getFieldOne);
// or like this. Will cause delayed runtime erros
usefulThingsService.makeUsefulThings(list, SomeClassEntity.class, "fieldTwo");
public class SomeClassEntity {
Integer fieldOne = 10;
Double fieldThree = 0.123;
public Integer getFieldOne() {
return fieldOne;
}
public void setFieldOne(Integer fieldOne) {
this.fieldOne = fieldOne;
}
public Double getFieldThree() {
return fieldThree;
}
public void setFieldThree(Double fieldThree) {
this.fieldThree = fieldThree;
}
}
public class UsefulThingsService<T> {
public void makeUsefulThings(Class<T> someClassBClass, String fieldName) {
// there is some code
}
}
希望在编译阶段而不是在运行时获得正确的引用。
更新:
我需要看起来比这更方便的代码:
Field fieldOne = null;
try {
fieldOne = SomeClassEntity.class.getDeclaredField("fieldOne");
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
usefulThingsService.makeUsefulThings(SomeClassEntity.class, fieldOne);
我为下一次澄清道歉。
更新 2:
- 该服务将列表与之前的列表进行比较,仅显示对象(列表项)的更改字段并更新原始列表中对象中的这些字段。
- 目前我在实体的字段上使用注释,它实际上是实体的 ID,当我需要更新源列表中的实体字段时,该 ID 用于检测相同的实体(旧的和新的)。
- 服务检测带注释的字段并将其用于下一个更新过程。
- 我想拒绝使用注释并直接在服务的构造函数中提供一个字段。或者使用其他可以在 class 和编译阶段的字段之间建立关系的东西。
假设您想要字段访问,因为您想要获取 和 设置值,您需要两个函数:
public class UsefulThingsService<T> {
public <V> void makeUsefulThings(List<T> list, Function<T,V> get, BiConsumer<T,V> set) {
for(T object: list) {
V v = get.apply(object);
// there is some code
set.accept(object, v);
}
}
}
和
usefulThingsService.makeUsefulThings(
list, SomeClassEntity::getFieldOne, SomeClassEntity::setFieldOne);
usefulThingsService.makeUsefulThings(
list, SomeClassEntity::getFieldThree, SomeClassEntity::setFieldThree);
但是,有些事情是开放的。例如,该服务应该如何对现场响应做一些有用的事情。 属性,甚至不知道它的实际类型。在您的示例中,两者都是 Number
的子类型,因此您可以声明 <V extends Number>
,因此该方法知道如何提取数值,但是,构造适当的结果对象需要指定另一个函数参数。
如何创建接受 Class 和 Field 作为参数的方法?像这样:
List<SomeClassEntity> list = ...;
// Service to make useful things around a list of objects
UsefulThingsService<SomeClassEntity> usefulThingsService = new UsefulThingsService<>();
// Maybe invoke like this. Did't work
usefulThingsService.makeUsefulThings(list, SomeClassEntity.class, SomeClassEntity::getFieldOne);
// or like this. Will cause delayed runtime erros
usefulThingsService.makeUsefulThings(list, SomeClassEntity.class, "fieldTwo");
public class SomeClassEntity {
Integer fieldOne = 10;
Double fieldThree = 0.123;
public Integer getFieldOne() {
return fieldOne;
}
public void setFieldOne(Integer fieldOne) {
this.fieldOne = fieldOne;
}
public Double getFieldThree() {
return fieldThree;
}
public void setFieldThree(Double fieldThree) {
this.fieldThree = fieldThree;
}
}
public class UsefulThingsService<T> {
public void makeUsefulThings(Class<T> someClassBClass, String fieldName) {
// there is some code
}
}
希望在编译阶段而不是在运行时获得正确的引用。
更新: 我需要看起来比这更方便的代码:
Field fieldOne = null;
try {
fieldOne = SomeClassEntity.class.getDeclaredField("fieldOne");
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
usefulThingsService.makeUsefulThings(SomeClassEntity.class, fieldOne);
我为下一次澄清道歉。
更新 2:
- 该服务将列表与之前的列表进行比较,仅显示对象(列表项)的更改字段并更新原始列表中对象中的这些字段。
- 目前我在实体的字段上使用注释,它实际上是实体的 ID,当我需要更新源列表中的实体字段时,该 ID 用于检测相同的实体(旧的和新的)。
- 服务检测带注释的字段并将其用于下一个更新过程。
- 我想拒绝使用注释并直接在服务的构造函数中提供一个字段。或者使用其他可以在 class 和编译阶段的字段之间建立关系的东西。
假设您想要字段访问,因为您想要获取 和 设置值,您需要两个函数:
public class UsefulThingsService<T> {
public <V> void makeUsefulThings(List<T> list, Function<T,V> get, BiConsumer<T,V> set) {
for(T object: list) {
V v = get.apply(object);
// there is some code
set.accept(object, v);
}
}
}
和
usefulThingsService.makeUsefulThings(
list, SomeClassEntity::getFieldOne, SomeClassEntity::setFieldOne);
usefulThingsService.makeUsefulThings(
list, SomeClassEntity::getFieldThree, SomeClassEntity::setFieldThree);
但是,有些事情是开放的。例如,该服务应该如何对现场响应做一些有用的事情。 属性,甚至不知道它的实际类型。在您的示例中,两者都是 Number
的子类型,因此您可以声明 <V extends Number>
,因此该方法知道如何提取数值,但是,构造适当的结果对象需要指定另一个函数参数。