首页 > 解决方案 > 只有一个具有自定义构造函数逻辑的对象在循环中被完全初始化

问题描述

我正在尝试使用以下代码将一个对象映射到另一个对象(Record-> ):ParsedAddress

public class ParsedAddress extends Address {

    private static final Map<Field, Consumer<String>> MAPPINGS = new EnumMap<>(Field.class);


    public ParsedAddress(final Record record, final List<Field> order) {
        super();

        this.mapFields(record, order);
    }

    private void mapFields(final Record record, final List<Field> order) {
        this.setupMapping();

        for (final Map.Entry<Field, Consumer<String>> mapping : MAPPINGS.entrySet()) {
            final Field field = mapping.getKey();
            final String value = record.getField(field, order);
            final Consumer<String> setter = mapping.getValue();

            setter.accept(value);
        }
    }

    private void setupMapping() {
        if (!MAPPINGS.isEmpty()) return;

        MAPPINGS.put(SALUTATION, this::setSalutation);
        MAPPINGS.put(FIRST_NAME, this::setFirstName);
        MAPPINGS.put(SURNAME, this::setSurname);
        // etc...
    }
}

Address是一个包含所有映射字段的数据对象。)

我这样调用构造函数:

records.stream()
       .map(record -> new ParsedAddress(record, ORDER))
       .collect(toUnmodifiableList());

但只有第一个“记录”被映射。结果集合包含一个ParsedAddress具有所有数据的集合(因此逻辑工作正常)和ParsedAddress具有null字段的 es。

我对其进行了调试,并设法将问题缩小到了setter.accept(value)一线。无论是在流还是循环中调用构造函数,它的工作原理都是一样的。

是关于对象初始化的吗?但是,为什么只有一个对象映射成功,而其他对象却没有呢?

编辑Record该类仅包含要映射的数据。这是getField方法:

public String getField(final Field field, final List<Field> order) {
    final int index = order.indexOf(field);

    return index == -1 ? null : this.data.get(index);
}

标签: java

解决方案


这里的问题是MAPPINGS地图是延迟加载的静态地图,但this关键字不是。

这导致映射只填充一次,但引用了到达它的第一个对象的公共设置器(延迟加载映射的对象)。

因此,每个消费者MAPPINGS都是同一个对象(延迟加载地图的对象)的公共设置器。

那很有趣!


推荐阅读