我已经获得了一个包含大约200个字段的类,其中使用反射读取它们的值。看起来基本上就像这个
for (Field f : this.getClass().getFields())
{
try
{
Object o = f.get(this);
if (f.getType() == String.class)
{
//do things with the string
}
}
catch (Exception ex)
{
logger.error("Cannot get value for field. {}", ex.getMessage());
}
}
这对于如此庞大的领域非常有效,因为我认为这是反思的重点。我被要求重构它,因为它很慢(是吗?)。
到目前为止,我唯一可以提出他的一个不合理的硬编码方法,还有另一种快速方法吗?
答案 0 :(得分:4)
首先,您应该使用分析器验证它确实很慢。反射比正常访问变量慢,但这并不一定意味着它是缓慢的来源。
如果您使用setter修改这些值,只要调用setter,您就可以重构该类以更新ko.computed.fn
。这样可以更快地访问字段而不是反射,但根据您的使用情况,可能无法访问这些字段。
答案 1 :(得分:3)
大部分时间用于获取Field对象(并可能过滤它们)实际的查找速度非常快。我使用ClassValue来缓存这些信息并加快速度。
public enum StringFields {
INSTANCE;
final ClassValue<List<Field>> fieldsCache = new ClassValue<List<Field>>() {
@Override
protected List<Field> computeValue(Class<?> type) {
return Collections.unmodifiableList(
Stream.of(type.getFields())
.filter(f -> f.getType() == String.class)
.peek(f -> f.setAccessible(true)) // turn off security check
.collect(Collectors.toList()));
}
};
public static List<Field> getAllStringFields(Class<?> type) {
return INSTANCE.fieldsCache.get(type);
}
}
答案 2 :(得分:1)
到目前为止,我唯一可以提出他的一个不合理的硬编码方法,还有另一种快速方法吗?
您可以使用反射来获取这些字段的getter并生成读取这些getter的代码。
然后,代码生成可以成为构建步骤的一部分。