简体   繁体   English

Java对象参考问题?

[英]Java Object Reference Problems?

I have the following classes; 我有以下课程;

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;
}

But for some odd reason, when method getSampleAjaxBinders() is called, it returns a list of AjaxRequestBinder objects with each and every one of them having; 但是出于某种奇怪的原因,当调用方法getSampleAjaxBinders() ,它将返回一个AjaxRequestBinder对象的列表,其中每个对象都有;

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

whereas this is required for only the last added item. 而只有最后添加的项目才需要这样做。 All the previously added items should simply have data = {} (empty map). 先前所有添加的项目都应仅具有data = {} (空映射)。 When I step-debug through the method, I find out that all is well until buildPayload(ServiceModule module, HttpMethod httpMethod) is called which then automatically overwrites the empty maps in the previously added items of the list. 当我逐步调试该方法时,我发现一切都很好,直到buildPayload(ServiceModule module, HttpMethod httpMethod) ,然后它会自动覆盖列表先前添加的项目中的空映射。

Can somebody please explain to me what might be responsible for this odd object reference problems being exhibited here; 有人可以给我解释一下这里出现的这个奇怪的对象引用问题的原因吗?

This happens because you always use a single instance of Payload , which happens to be set for RABBIT . 发生这种情况的原因是,您始终只使用一个Payload实例,而该实例恰好是为RABBIT设置的。

Your buildPayload method returns payload which is set to the shared instance: 您的buildPayload方法返回设置为共享实例的payload

Payload payload = Payload.INSTANCE;

At the same time, when you pass null payload to AjaxRequestBinder constructor, the constructor uses the same Payload.INSTANCE : 同时,当您将null有效负载传递给AjaxRequestBinder构造函数时,该构造函数使用相同的Payload.INSTANCE

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

You can fix it either by making Payload constructor public and creating new instances in buildPayload , or making a separate empty instance of Payload for using in cases when null is supplied to AjaxRequestBinder constructor: 您可以通过以下方式解决此问题:将Payload构造函数公开,并在buildPayload创建新实例,或者将Payload单独设置为空实例,以在向AjaxRequestBinder构造函数提供null情况下使用:

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();

Note that if you continue with the shared instance approach above, you would need to clear the map in the buildPayload method. 请注意,如果继续上述共享实例方法,则需要在buildPayload方法中清除映射。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM