2017-07-19 9 views
1

私は以下のクラスを持っています。Javaオブジェクト参照の問題?

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

'payload.getMap()'と 'Payload.INSTANCE.getMap()'はまったく同じオブジェクトです。リスト全体に1つのマップしかありません –

+1

この状況では、コレクションに追加されたすべてのオブジェクトが異なるため、重複は実際にこの質問に答えません。この問題は、* empty *インスタンスの代わりに* shared *インスタンスを使用して誤って重複してしまうことになります。質問を再開する投票。 – dasblinkenlight

答えて

4

これは、常にPayloadという単一インスタンスを使用するためです。これは、RABBITに設定されていることがあります。

あなたbuildPayload方法は、共有インスタンスに設定されている​​返す:あなたはAjaxRequestBinderコンストラクタにnullペイロードを渡す際に、コンストラクタは同じPayload.INSTANCEを使用して、同時に

Payload payload = Payload.INSTANCE; 

を:

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

Payloadコンストラクタをpublicにして、新しいインスタンスをに作成することで修正できます10、またはnullAjaxRequestBinderコンストラクタに供給されたときのケースで使用するためのPayloadの別々の空のインスタンスを作る:あなたは上記の共有インスタンスのアプローチを続けるならば、あなたがマップをクリアする必要があると

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方法。

関連する問題