如果 java 是按值传递的,为啥我的对象在执行方法后会发生变化?

Posted

技术标签:

【中文标题】如果 java 是按值传递的,为啥我的对象在执行方法后会发生变化?【英文标题】:If java is passed-by-value why my object changes after executing the method?如果 java 是按值传递的,为什么我的对象在执行方法后会发生变化? 【发布时间】:2015-08-03 06:32:38 【问题描述】:

我正在调试我的方法,它以某种方式更新了我的 element 变量。即使我不在方法中使用该变量。

代码:

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 正在更改

这是我调用方法的方式:

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

我想要的只是复制字段映射,通过该方法处理它,然后返回并将其添加到fieldMappings 列表中。

问题是step.mappingselement 的一部分,但step.mappings 被放入ArrayList fieldMapping。因此,我认为元素永远不应该被任何东西编辑。

【问题讨论】:

你是在重新分配,而不是直接改变。 “我正在调试我的方法,它以某种方式更新了我的元素变量” - 不,它没有。 element 变量的值与之前完全相同——它是一个对象的reference。该对象中的数据可能已更改(尚不清楚它在您发布的代码中的位置),但这不是一回事。 这里也有一些很好的答案***.com/q/7893492/2991525 我投票支持重新打开,因为这并不是真正的重复:OP 不是关于 java 是按值调用的;这是关于一个特定问题的! fieldMappings == element.processingSteps的情况吗?也就是说,这两个声明指向same引用? 【参考方案1】:

我相信这是因为更改此代码中的 fieldMapping 也会更改元素,因为两者都是对同一对象的“引用”:

fieldMapping.targetEntityFieldId = cdoFieldSplit[0];

要验证是否是这种情况,请添加条件调试中断(或 if 语句和打印/日志)来检查两个对象实例的相等性。

发生这种情况是因为您在以下代码中将 fieldMapping 设置为等于 element.processingSteps.iterator() 指向的对象。

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

如果您不希望这种行为,那么您需要在初始化 fieldMapping 时“深拷贝”step.mappings 对象。

【讨论】:

我觉得你说得对,我一回家就试试。但是,您如何称呼这种行为?即使我创建了新的 ArrayList fieldMapping 并将 step.mappings 放在那里,它仍然只是对同一个对象的引用? ArrayList 是指针的容器,指针是存储引用的对象。这启用了 java 的按值性质,其中指针按值复制,但指针引用的对象(即指针的值)仍然相同。这使得 Java 自诞生以来的速度大大提高,因为它可以避免复制整个对象(这在 Java 中变得相当大)。

以上是关于如果 java 是按值传递的,为啥我的对象在执行方法后会发生变化?的主要内容,如果未能解决你的问题,请参考以下文章

JavaScript 是按引用传递还是按值传递语言?

Ruby 是按值传递还是按引用传递? [复制]

列表是按值传递的吗?

java中参数传递方式

java 值传递 数组传递

java中参数传递--值传递,引用传递