Java对象引用问题?

时间:2017-07-19 12:41:08

标签: java builder object-reference builder-pattern

我有以下课程;

public class Payload{

    private Map<String, Object> map;

    public static Payload INSTANCE = new Payload();

    private Payload(){
        map = new HashMap<>();
    }

    public Payload put(String key, Object value){
        map.put(key, value);
        return this;
    }

    public Map<String, Object> getMap(){
        return map;
    }
}

public class AjaxRequestBinder {

    private String url;
    private String method;
    private Map<String, Object> data;
    private String dataType;

    public AjaxRequestBinder(String url, String method, Payload payload, AjaxDataType dataType) {
        this.url = url;
        this.method = method;
        this.data = payload != null ? payload.getMap() : Payload.INSTANCE.getMap();
        this.dataType = dataType != null ? dataType.name() : AjaxDataType.html.name();
    }
    //... getters() & setters()
}

public List<AjaxRequestBinder> getSampleAjaxBinders() throws Exception {
    List<AjaxRequestBinder> requestBinders = new ArrayList<>();
    requestBinders.add(new AjaxRequestBinder(getEndpointURL(ServiceModule.CAT), HttpMethod.GET.name(), null, AjaxDataType.json));
    requestBinders.add(new AjaxRequestBinder(getEndpointURL(ServiceModule.DOG), HttpMethod.GET.name(), null, AjaxDataType.json));
    requestBinders.add(new AjaxRequestBinder(getEndpointURL(ServiceModule.CHICKEN), HttpMethod.GET.name(), null, AjaxDataType.json));
    requestBinders.add(new AjaxRequestBinder(getEndpointURL(ServiceModule.GOAT), HttpMethod.GET.name(), null, AjaxDataType.json));
    requestBinders.add(new AjaxRequestBinder(getEndpointURL(ServiceModule.RABBIT), HttpMethod.POST.name(), buildPayload(ServiceModule.RABBIT, HttpMethod.POST), AjaxDataType.json));
    return requestBinders;
}

public Payload buildPayload(ServiceModule module, HttpMethod httpMethod) throws Exception {
    Payload payload = Payload.INSTANCE;
    module = module != null ? module : ServiceModule.NONE;

    if(httpMethod.equals(HttpMethod.POST)){

        switch(module){
            case CAT:{
                // Do nothing
            }break;
            case DOG:{
                // Do nothing
            }break;
            case CHICKEN:{
                // Do nothing
            }break;
            case GOAT:{
                // Do nothing
            }break;
            case RABBIT:{
                payload.put("color", "white").put("action", "hops");
            }break;
        }
    }else{
        throw new NotYetImplementedException();
    }
    return payload;
}

但是由于一些奇怪的原因,当调用方法getSampleAjaxBinders()时,它返回AjaxRequestBinder个对象的列表,每个对象都有;

data = {"color":"white", "action":"hops"}

而这只是最后添加的项目所必需的。之前添加的所有项目都应该只有data = {}(空地图)。当我通过该方法进行步骤调试时,我发现在调用buildPayload(ServiceModule module, HttpMethod httpMethod)之前一切都很好,然后自动覆盖先前添加的列表项中的空映射。

有人可以向我解释一下这个奇怪的物体参考问题可能会对这个问题负责吗?

1 个答案:

答案 0 :(得分:4)

这是因为您总是使用Payload的单个实例,恰好是为RABBIT设置的。{/ p>

您的buildPayload方法返回设置为共享实例的payload

Payload payload = Payload.INSTANCE;

同时,当您将null有效负载传递给AjaxRequestBinder构造函数时,构造函数使用相同的Payload.INSTANCE

this.data = payload != null ? payload.getMap() : Payload.INSTANCE.getMap();

您可以通过将Payload构造函数公开并在buildPayload中创建新实例,或者在Payload的情况下创建null的单独空实例来解决此问题。提供给AjaxRequestBinder构造函数:

public static final Payload INSTANCE = new Payload();
// Add this line to Payload
public static final Payload EMPTY = new Payload();
...
// Use EMPTY payload when the caller does not supply an actual one:
this.data = payload != null ? payload.getMap() : Payload.EMPTY.getMap();

请注意,如果您继续使用上述共享实例方法,则需要使用buildPayload方法清除地图。