Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/316.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 比较两个无关对象的字段_Java_Reflection_Comparison_Compare_Field - Fatal编程技术网

Java 比较两个无关对象的字段

Java 比较两个无关对象的字段,java,reflection,comparison,compare,field,Java,Reflection,Comparison,Compare,Field,我有两个不同类的对象,它们共享一些具有相同名称和类型的字段。这两个对象彼此不相关。我不可能创建接口或父类 现在我想比较这些共享字段,据我所知,这应该可以使用反射 以下是我为这种比较方法编写的步骤: Field[] inputFields = input.getClass().getDeclaredFields(); for (Field field : inputFields ) { log.info(field.getName() + " : " + field.getType());

我有两个不同类的对象,它们共享一些具有相同名称和类型的字段。这两个对象彼此不相关。我不可能创建接口或父类

现在我想比较这些共享字段,据我所知,这应该可以使用反射

以下是我为这种比较方法编写的步骤:

Field[] inputFields = input.getClass().getDeclaredFields();
for (Field field : inputFields ) {
    log.info(field.getName() + " : " + field.getType());
}
将有一个名为
数据库
的对象,将
输入字段
与该对象的字段进行比较

不幸的是,我不知道如何获取字段的值。你有什么提示给我吗


好的,使用
field.get(input)
我现在已经得到了值,但可能我错了,这不是我需要的。 实际上,我想将这个字段与另一个字段进行比较,所以我需要对这个字段调用equals方法。但首先我得把它放到合适的课堂上。
那么是否有类似于
((field.getClass())field).equals(…)
的东西可以使用呢?

我想您正在寻找:


查看Sun的Java教程。用示例回答您的特定问题。

这里是这个问题的解决方案,一个名为
FieldHelper
的实用程序类,它有一个方法

Map<String, Object[]> properties =
    FieldHelper.getCommonProperties(Object a, Object b)
映射属性=
FieldHelper.getCommonProperties(对象a、对象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);
        }
    }
公共最终类FieldHelper{
私有FieldHelper(){}
私有静态最终映射,映射>();
/**
*返回字段名到{@link PropertyDescriptor}对象的映射
*给豆子。
*/
公共静态映射getBeanProperties(最终对象o){
试一试{
最终类clazz=o.getClass();
地图描述符;
if(cache.containsKey(clazz)){
描述符=cache.get(clazz);
}否则{
最终BeanInfo BeanInfo=
getBeanInfo(clazz,Object.class);
描述符=新树映射();
对于(final PropertyDescriptor pd:beanInfo.getPropertyDescriptors()){
descriptor.put(pd.getName(),pd);
}
cache.put(clazz,
新树形图(描述符);
}
最终地图beanProperties=描述符;
返回Bean属性;
}捕获(最终内省异常e){
抛出新的IllegalStateException(“无法获取bean元数据”,e);
}
}
/**
*返回所有字段名及其各自的值的映射
*对象有共同点。警告:字段值可以是不同的
*类型。
*/
公共静态映射getCommonProperties(最终对象a,
最终目标(b){
最终地图aProps=getBeanProperties(a);
最终映射bProps=getBeanProperties(b);
最终设置aKeys=aProps.keySet();
最终设置bKeys=bProps.keySet();
阿凯斯·雷塔纳尔(bKeys);
bKeys.restainall(aKeys);
最终映射=新树映射();
for(最终字符串属性名称:aKeys){
最终对象aVal=getPropertyValue(a,aProps.get(propertyName));
final Object bVal=getPropertyValue(b,bProps.get(propertyName));
put(propertyName,新对象[]{aVal,bVal});
}
返回图;
}
/**
*给定bean和{@linkpropertydescriptor},返回bean属性的值。
*/
私有静态对象getPropertyValue(最终对象a,
最终属性描述器(属性描述器){
试一试{
返回propertyDescriptor.getReadMethod().invoke(a);
}捕获(最终非法辩论例外e){
抛出新的IllegalStateException(“坏方法参数”,e);
}捕获(最终非法访问例外e){
抛出新的非法状态异常(“无法访问方法”,e);
}捕获(最终调用TargetException e){
抛出新的IllegalStateException(“调用错误”,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]);
    }
}
publicstaticvoidmain(最终字符串[]args){
福班{
私有字符串abc=“abc”;
私有字符串defy=“defy”;
私有字符串ghi=“ghi”;
私有字符串jkl=“jkl”;
//剥离吸气剂和塞特剂
//他们必须在那里,这样才能起作用
}
分类栏{
私有布尔abc=true;
私有整数def=3;
专用字符串ghix=“ghix3”;
私有日期jkl=新日期();
//剥离吸气剂和塞特剂
//他们必须在那里,这样才能起作用
}
最终贴图属性=
getCommonProperties(新Foo(),新Bar());
for(最终条目:properties.entrySet()){
System.out.println(“字段:“+entry.getKey()+”,值a:”
+entry.getValue()[0]+”,值b:“+entry.getValue()[1]);
}
}
输出:

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 10月12日14:03:31 CEST 2010


注意:这段代码实际上并不读取字段,它遵循java bean约定,而是使用getter。重写它以使用字段很容易,但我建议不要这样做。

为什么要使用反射?编写一个将两个对象都作为参数并比较字段值的方法不是更容易吗(假设有getter)?是的,但这会非常乏味。使用反射不是吗?当然,除非您知道这些字段的类型和/或名称将发生变化。如果编写与具体类型的比较过于乏味(如您所写),我建议您使用反射来生成代码中繁琐的部分。然后可以手动对生成的代码进行进一步微调。这将使您在运行时有更高的速度,并有可能自己查看比较逻辑。@Neeme oh com