2

I was debugging my method and it somehow updates my element variable. Even if I don't work with that variable from within the method.

CODE:

private static List<Mapping> createFormFieldsMapping(ArrayList<String> CDOfields,
            List<Mapping> fieldMappings, Element element) {
        System.out.println(" - Creating field mappings for "+element.name);
        for (Mapping fieldMapping : fieldMappings){
            if (fieldMapping.targetEntityFieldId!=null){
                String formField = getContactFieldNameById(fieldMapping.targetEntityFieldId);
                formField = formField.trim();
                formField = formField.replaceAll("-", "");
                formField = formField.replaceAll("_", "");
                formField = formField.replaceAll(" ", "");
                formField = formField.toLowerCase();
                Boolean matchFound = false;
                for (String cdoField : CDOfields){
                    String[] cdoFieldSplit = cdoField.split(";",-1);
                    String cdoFieldModified =cdoFieldSplit[1].trim();
                    cdoFieldModified = cdoFieldModified.replaceAll("-", "");
                    cdoFieldModified = cdoFieldModified.replaceAll("_", "");
                    cdoFieldModified = cdoFieldModified.replaceAll(" ", "");
                    cdoFieldModified = cdoFieldModified.toLowerCase();
                    if (cdoFieldModified.equals(formField)){
                        fieldMapping.targetEntityFieldId = cdoFieldSplit[0];
                        matchFound = true;
                        break;
                    }
                    if (!matchFound){
                        // WRITE NOT MATCHED FORM FIELD TO A FILE
                    }
                }
            }
        }

element.processingSteps.targetEntityFieldId is being changed

This is the way I call the method:

List<Mapping> fieldMapping = new ArrayList<Mapping>();
Iterator<ProcessingStep> i = element.processingSteps.iterator();

while (i.hasNext()) {
       ProcessingStep step = i.next(); 
       if (step.type.equals("FormStepCreateUpdateContactFromFormField")){
           fieldMapping = step.mappings;
           step.execute = "never";
           //i.remove();
        }
     }
// Update contact field IDs with CDO field IDs
    fieldMapping = createFormFieldsMapping(CDOfields, fieldMapping, element);

Everything I wanted was to kind of copy field mapping, process it by that method and then return back and add it to list of fieldMappings.

The thing is that step.mappings is part of element, but that step.mappings is being put to an ArrayList fieldMapping. By that I would assume that element should never be edited by anything.

11
  • You are reassigning, not directly changing. Commented May 21, 2015 at 14:13
  • "I was debugging my method and it somehow updates my element variable" - no it doesn't. The value of the element variable is exactly the same as it was before - it's a reference to an object. The data within that object has may have changed (it's not clear where it would within the code you've posted), but that's not the same thing. Commented May 21, 2015 at 14:14
  • 1
    Also some good answers here stackoverflow.com/q/7893492/2991525 Commented May 21, 2015 at 14:14
  • 1
    I'm voting for reopen since this isn't really a duplicate: the OP isn't about java being call-by-value; It's about a specific problem! Commented May 21, 2015 at 15:02
  • 1
    Is it the case that fieldMappings == element.processingSteps? That is to say, that those two declarations point to the same reference? Commented May 21, 2015 at 15:25

1 Answer 1

1

I believe this is because changing fieldMapping in this code also changes element because both are "references" to the same object:

fieldMapping.targetEntityFieldId = cdoFieldSplit[0];

To verify this is the case, add a conditional debug break (or an if-statement and a print/log) that checks the equality of the two object instances.

This is happening because you are setting fieldMapping equal to the object pointed to by your element.processingSteps.iterator() in following code.

Iterator<ProcessingStep> i = element.processingSteps.iterator();

while (i.hasNext()) {
       ProcessingStep step = i.next(); 
       if (step.type.equals("FormStepCreateUpdateContactFromFormField")){
           fieldMapping = step.mappings;
           step.execute = "never";
           //i.remove();
        }
     }
// Update contact field IDs with CDO field IDs
    fieldMapping = createFormFieldsMapping(CDOfields, fieldMapping, element);

If you do not want this behavior, then you need to "deep copy" the step.mappings object when initializing fieldMapping.

Sign up to request clarification or add additional context in comments.

2 Comments

I think you are right, I will try it as soon as I get home. However, how do you call that behavior? That even if I have created new ArrayList fieldMapping and put step.mappings in there, it is still just a reference to the same object?
ArrayList is a container for pointers, and pointers are objects that store a reference. This enables the By-Value nature of java, where the pointers are copied By-Value, but the object referenced by the pointer (i.e. the pointer's value) is still the same. This enables much of Java's speed since inception, since it could avoid copying entire objects (which get pretty big in Java).

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.