我有两个不同类的对象,它们共享一些具有相同名称和类型的字段。这两个对象彼此无关。我不可能创建一个接口或父类。
现在我想比较这些共享字段,据我所知,这应该可以使用反射。
这些是我为这种比较方法编写的步骤:
Field[] inputFields = input.getClass().getDeclaredFields();
for (Field field : inputFields ) {
log.info(field.getName() + " : " + field.getType());
}
将会有一个名为database
的对象与inputFields
进行比较。
不幸的是我不知道如何获得我的字段的价值。你有什么提示吗?
好的,field.get(input)
我现在有了价值,但也许我错了,这不是我需要的。
实际上,我想将此字段与另一个字段进行比较,因此我需要在此字段上调用equals方法。但起初我必须把它投到适当的班级。
那么((field.getClass()) field).equals(...)
会有用吗?
答案 0 :(得分:2)
我认为您正在寻找Field.get()
:
for (Field field : inputFields ) {
log.info(field.getName() + " : "
+ field.getType() + " = "
+ field.get(input);
}
答案 1 :(得分:0)
查看Sun Java教程的dedicated chapter。 This page以示例回答您的特定问题。
答案 2 :(得分:0)
以下是此问题的解决方案,一个名为FieldHelper
的实用程序类,它有一个方法
Map<String, Object[]> properties =
FieldHelper.getCommonProperties(Object a, Object b)
返回的地图将字段名称作为键,将两个字段值的数组作为值:
public final class FieldHelper{
private FieldHelper(){}
private static final Map<Class<?>, Map<String, PropertyDescriptor>> cache =
new HashMap<Class<?>, Map<String, PropertyDescriptor>>();
/**
* Return a Map of field names to {@link PropertyDescriptor} objects for a
* given bean.
*/
public static Map<String, PropertyDescriptor> getBeanProperties(final Object o){
try{
final Class<?> clazz = o.getClass();
Map<String, PropertyDescriptor> descriptors;
if(cache.containsKey(clazz)){
descriptors = cache.get(clazz);
} else{
final BeanInfo beanInfo =
Introspector.getBeanInfo(clazz, Object.class);
descriptors = new TreeMap<String, PropertyDescriptor>();
for(final PropertyDescriptor pd : beanInfo.getPropertyDescriptors()){
descriptors.put(pd.getName(), pd);
}
cache.put(clazz,
new TreeMap<String, PropertyDescriptor>(descriptors));
}
final Map<String, PropertyDescriptor> beanProperties = descriptors;
return beanProperties;
} catch(final IntrospectionException e){
throw new IllegalStateException("Can't get bean metadata", e);
}
}
/**
* Return a Map of all field names and their respective values that two
* objects have in common. Warning: the field values can be of different
* types.
*/
public static Map<String, Object[]> getCommonProperties(final Object a,
final Object b){
final Map<String, PropertyDescriptor> aProps = getBeanProperties(a);
final Map<String, PropertyDescriptor> bProps = getBeanProperties(b);
final Set<String> aKeys = aProps.keySet();
final Set<String> bKeys = bProps.keySet();
aKeys.retainAll(bKeys);
bKeys.retainAll(aKeys);
final Map<String, Object[]> map = new TreeMap<String, Object[]>();
for(final String propertyName : aKeys){
final Object aVal = getPropertyValue(a, aProps.get(propertyName));
final Object bVal = getPropertyValue(b, bProps.get(propertyName));
map.put(propertyName, new Object[] { aVal, bVal });
}
return map;
}
/**
* Return the value of a bean property, given the bean and the {@link PropertyDescriptor}.
*/
private static Object getPropertyValue(final Object a,
final PropertyDescriptor propertyDescriptor){
try{
return propertyDescriptor.getReadMethod().invoke(a);
} catch(final IllegalArgumentException e){
throw new IllegalStateException("Bad method arguments", e);
} catch(final IllegalAccessException e){
throw new IllegalStateException("Can't access method", e);
} catch(final InvocationTargetException e){
throw new IllegalStateException("Invocation error", e);
}
}
测试代码:
public static void main(final String[] args){
class Foo{
private String abc = "abc";
private String defy = "defy";
private String ghi = "ghi";
private String jkl = "jkl";
// stripped getters and setters
// they must be there for this to work
}
class Bar{
private Boolean abc = true;
private Integer def = 3;
private String ghix = "ghix3";
private Date jkl = new Date();
// stripped getters and setters
// they must be there for this to work
}
final Map<String, Object[]> properties =
getCommonProperties(new Foo(), new Bar());
for(final Entry<String, Object[]> entry : properties.entrySet()){
System.out.println("Field: " + entry.getKey() + ", value a: "
+ entry.getValue()[0] + ", value b: " + entry.getValue()[1]);
}
}
<强>输出:强>
字段:abc,值a:abc,值b:true
字段:jkl,值a:jkl,值b:Tue Oct 12 14:03:31 CEST 2010
注意:此代码实际上并不读取字段,它遵循java bean约定并使用getter代替。将它重写为使用字段会很容易,但我会反对它。