Java对象引用问题?

Java对象引用问题?,java,builder,object-reference,builder-pattern,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){

我有以下课程

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;
}
公共类有效负载{
私人地图;
公共静态负载实例=新负载();
专用有效载荷(){
map=新的HashMap();
}
公共有效负载put(字符串键、对象值){
map.put(键、值);
归还这个;
}
公共地图getMap(){
返回图;
}
}
公共类AjaxRequestBinder{
私有字符串url;
私有字符串方法;
私有地图数据;
私有字符串数据类型;
公共AjaxRequestBinder(字符串url、字符串方法、有效负载、AjaxDataType数据类型){
this.url=url;
这个方法=方法;
this.data=payload!=null?payload.getMap():payload.INSTANCE.getMap();
this.dataType=dataType!=null?dataType.name():AjaxDataType.html.name();
}
//…getters()和setters()
}
公共列表getSampleAjaxBinders()引发异常{
List requestBinders=new ArrayList();
add(新的AjaxRequestBinder(getEndpointURL(ServiceModule.CAT),HttpMethod.GET.name(),null,AjaxDataType.json));
add(新的AjaxRequestBinder(getEndpointURL(ServiceModule.DOG),HttpMethod.GET.name(),null,AjaxDataType.json));
add(新的AjaxRequestBinder(getEndpointURL(ServiceModule.CHICKEN),HttpMethod.GET.name(),null,AjaxDataType.json));
add(新的AjaxRequestBinder(getEndpointURL(ServiceModule.GOAT),HttpMethod.GET.name(),null,AjaxDataType.json));
add(新的AjaxRequestBinder(getEndpointURL(ServiceModule.RABBIT)、HttpMethod.POST.name()、buildPayload(ServiceModule.RABBIT、HttpMethod.POST)、AjaxDataType.json));
返回活页夹;
}
公共有效负载buildPayload(ServiceModule模块,HttpMethod HttpMethod)引发异常{
有效载荷=Payload.INSTANCE;
模块=模块!=null?模块:ServiceModule.NONE;
if(httpMethod.equals(httpMethod.POST)){
开关(模块){
案例类别:{
//无所事事
}中断;
个案犬:{
//无所事事
}中断;
个案鸡:{
//无所事事
}中断;
个案山羊:{
//无所事事
}中断;
病例兔:{
有效载荷。放置(“颜色”、“白色”)。放置(“动作”、“跳跃”);
}中断;
}
}否则{
抛出新的NotYetImplementedException();
}
返回有效载荷;
}
但由于某种奇怪的原因,当调用方法
getSampleAjaxBinders()
时,它返回一个
AjaxRequestBinder
对象列表,其中每个对象都有

data={“color”:“white”,“action”:“hops”}

然而,这仅适用于最后添加的项目。所有先前添加的项都应该只有
数据={}
(空映射)。当我逐步调试该方法时,我发现一切正常,直到调用
buildPayload(ServiceModule模块,HttpMethod HttpMethod)
,然后自动覆盖列表中先前添加的项目中的空映射


有人能给我解释一下,是什么导致了这里出现的这种奇怪的对象引用问题

之所以会发生这种情况,是因为您总是使用
有效负载的单个实例,而该实例恰好是为
RABBIT
设置的

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

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

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
方法中的映射。

之所以会发生这种情况,是因为您始终使用
Payload
的单个实例,而该实例恰好被设置为
RABBIT

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

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

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
方法中的映射。

payload.getMap()
payload.instance.getMap()
是完全相同的对象。列表中只有一个映射。重复的映射并不能真正回答这个问题,因为在这种情况下,添加到集合中的所有对象都是不同的。问题归结为无意中使用共享实例来代替空实例,这与重复实例不同。投票重新打开问题。
payload.getMap()
payload.INSTANCE.getMap()
是完全相同的对象。列表中只有一个映射。重复的映射并不能真正回答这个问题,因为在这种情况下,添加到集合中的所有对象都是不同的。问题归结为无意中使用共享实例来代替空实例,这与重复实例不同。表决重新开始问题。