通过Java反射重新创建(通用)成员并填充/分配字段成员



我有一组类,其中包含任意数量的非自定义成员——只有基元、包装器等。;它们中的一些可以用CCD_ 1进行注释以便进行不同的处理。所有类型都实现Envelope

我正在创建两个Map(基于给定类型(,存储"字段名称"(作为关键字(和"字段值"(作为值(。

问题是当我试图再次基于Maps重新创建类型时。这就是我目前所拥有的:

import io.shido.domain.Envelope;
import org.apache.commons.lang3.reflect.FieldUtils;
import java.util.Map;
public final class Factory<T extends Envelope> {
private final Map<String, Object> regularMembers;
private final Map<String, Object> secureMembers;
public Factory(final Map<String, Object> regularMembers, final Map<String, Object> secureMembers) {
this.regularMembers = regularMembers;
this.secureMembers = secureMembers;
}
public T build() {
try {
final ParameterizedType superClass = (ParameterizedType) getClass().getGenericSuperclass(); // This doesn't work >:(
final Class<T> type = (Class<T>) superClass.getActualTypeArguments()[0];
final T result = type.newInstance();
regularMembers.forEach((fieldName, fieldValue) -> assign(result, fieldName, fieldValue));
secureMembers.forEach((fieldName, fieldValue) -> assign(result, fieldName, fieldValue));
return result;
} catch (final Exception e) {
logger.error("Cannot build type based on input parameters due to:", e);
throw new IllegalStateException(e.toString());
}
}
private void assign(final T type, final String fieldName, final Object fieldValue) {
try {
FieldUtils.getField(type.getClass(), fieldName).set(type, fieldValue);
} catch (final IllegalAccessException e) {
e.printStackTrace();
}
}
}

有什么线索可以找到吗?我可以使用任何图书馆。


我唯一的限制是当前类型没有setter——我不能添加这些,我使用的是Java8

例如,这是一个例子:

public final class ExampleType implements Envelope {
@Encrypted
private String first;
private String second;
@Encrypted
private String third;
public ExampleType() { }
public ExampleType(final String first, final String second, final String third) {
this.first = first;
this.second = second;
this.third = third;
}
public String getFirst() { return first; }
public String getSecond() { return second; }
public String getThird() { return third; }
}

要扩展我的评论,请尝试以下操作(未经测试(:

import io.shido.domain.Envelope;
import org.apache.commons.lang3.reflect.FieldUtils;
import java.util.Map;
public final class Factory<T extends Envelope> {
private final Class<T> clazz;
private final Map<String, Object> regularMembers;
private final Map<String, Object> secureMembers;
public Factory(final Class<T> clazz, final Map<String, Object> regularMembers, final Map<String, Object> secureMembers) {
this.clazz = clazz;
this.regularMembers = regularMembers;
this.secureMembers = secureMembers;
}
public T build() {
try {
final T result = clazz.newInstance();
regularMembers.forEach((fieldName, fieldValue) -> assign(result, fieldName, fieldValue));
secureMembers.forEach((fieldName, fieldValue) -> assign(result, fieldName, fieldValue));
return result;
} catch (final Exception e) {
logger.error("Cannot build type based on input parameters due to:", e);
throw new IllegalStateException(e.toString());
}
}
private void assign(final T type, final String fieldName, final Object fieldValue) {
try {
FieldUtils.getField(type.getClass(), fieldName).set(type, fieldValue);
} catch (final IllegalAccessException e) {
e.printStackTrace();
}
}
}

如果字段是私有的,我认为您需要使它们可访问。在您的试块中:

Field f = FieldUtils.getField(type.getClass(), fieldName);
f.setAccessible(true);
f.set(type, fieldValue);

您可能希望通过构造函数传递泛型对象(Class<T>(的类,并直接使用它来实例化它。

public final class Factory<T extends Envelope> {
private Class<T> clazz;
// maps omitted
public Factory(Class<T> clazz, Map<String, Object> rm, Map<String, Object> sm) {
this.clazz = clazz;
this.regularMembers = rm;
this.secureMembers = sm;
}
...
}

然后在T build()方法中使用Class::instance

public T build() {
try {
final T result = clazz.newInstance();
...
} ...
}

最新更新