【问题标题】:Issue with pass by value in java [duplicate]java中按值传递的问题[重复]
【发布时间】:2015-12-08 02:47:36
【问题描述】:

Java 支持按值传递(始终适用于副本),但是当您传递用户定义的对象时,它会更改实际对象(通过引用传递但没有指针更改),我理解这是为什么下面的 changeObject2CLEAR 方法实际上是在改变对象的值吗?相反,它必须在副本上工作?


import java.util.HashMap;
import java.util.Map;

public class PassBy {

    class CustomBean {
        public CustomBean() {

        }

        private int id;
        private String name;

        public int getId() {
            return id;
        }
        public void setId(int id) {
            this.id = id;
        }
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }   

        @Override
        public String toString() {
            return id + ", " + name;
        }
    }

    public Map<Integer, String> changeObject2NULL (Map<Integer, String> m) {
        m = null;
        return m;
    }

    public Map<Integer, String> changeObject2CLEAR (Map<Integer, String> m) {
        m.clear();
        return m;
    }

    public CustomBean changeCustomObject (CustomBean _e) {

        _e.setId(_e.getId() + 1);
        return _e;
    }

    public static void main(String[] args) {

    PassBy passby = new PassBy();

    Map<Integer, String> map = new HashMap<Integer, String>();
    map.put(1, "value");

    CustomBean bean = passby.new CustomBean();
    bean.setId(1);
    bean.setName("arun");

    // Initial Value
    System.out.println(map.toString());
    System.out.println(bean.toString());
    System.out.println("-------------------------");

    // Pass by value works fine
    passby.changeObject2NULL(map);
    passby.changeCustomObject(bean);

    // Custom object value changes since we pass as the object reference but Map remains with actual value
    System.out.println(map.toString());
    System.out.println(bean.toString());
    System.out.println("-------------------------");

    // Testing Pass by value - CANT UNDERSTAND why it changed the object since it has to be pass-by-value and not by ref in this case ??
    // Why setting to null not chainging the value but clear does ?
    passby.changeObject2CLEAR(map);
    System.out.println(map.toString());

    }
}

【问题讨论】:

  • 您正在按值传递 reference。谷歌上有很多关于这个的。好问题。
  • @Arun 我已经更新了我的答案,以解决您问题的精炼形式
  • 简而言之,changeObject2NULL(Map&lt;Integer, String&gt; m) 包含自己的 local 变量 m,它恰好也是方法参数。当您使用此方法时,如changeObject2NULL(map) m 会复制有关map 持有哪个对象的信息(此地址是map 变量的)。因此,当您调用m.clear() 时,它会在map 持有的同一对象上调用clear 方法,因此您可以通过map 查看该对象的新状态。当您调用m = null 时,您只需将m 持有的对象更改为null;这不会影响map 也不会影响它所指的对象。

标签: java pass-by-value


【解决方案1】:

AFAIK Java 仅按值传递,但值实际上是引用

【讨论】:

  • 这适用于Object 实例,但不适用于原始类型
  • 为什么设置对象为null是传值,而clear方法是传值?
  • null 是一个引用,因此通过分配 null,您正在更改当前范围内的引用,从而“丢失”您正在处理的对象,而 clear 更改您引用的对象传入函数
【解决方案2】:

所以让我试着帮助你理解,Java 总是按值传递,但我相信你知道所有对象实例实际上都是指向这些对象的指针。现在,当您发送对象时,您将传递对象地址的值。如果您对对象本身进行任何更改(例如 m.clear()),那么它会转到该地址,类型转换对象并对其进行操作。但是如果你改变指针本身,比如 m = null,那么只有你持有的地址的副本会被改变。

【讨论】:

  • 反对者,想发表评论吗?这是正确答案。至少,没有一个错误的答案。
  • 由于问题是重复的,因此我将对这个问题和重复问题中的所有答案进行投票。副本中的答案远远优于这个答案。所以IMO,它没有添加任何有用的东西。如果你有什么要补充的,那就把答案加到副本里。
  • @Bathsheba 虽然您当然可以随意投反对票,但我发现一个好的经验法则是在问题严重错误或有害时投反对票。如果它不如另一个答案好,那么我会投票给更好的答案,而让不太好的答案保持不变。换句话说,我帮助更好的答案上升到顶部,而不用担心试图让不太好的答案下沉。
  • 这是看待事物的好方法。我撤回了反对票。
  • David / Bathsheba / LanguidSquid / 其他受人尊敬的贡献者...为什么将对象设置为 null 是传递值但 clear 方法是传递引用?
【解决方案3】:

当您拨打changeObject2CLEAR

passby.changeObject2CLEAR(map);

您正在传递实例map

在方法changeObject2CLEAR

public Map<Integer, String> changeObject2CLEAR (Map<Integer, String> m) {
    m.clear();
    return m;
}

您在同一个实例map 上执行.clear(),即使在方法中它被称为m

作为理解练习,请注意以下方法将做同样的事情。

public void changeObject2CLEAR (Map<Integer, String> m) {
    m.clear();
}

请注意,您不必返回 Map&lt;Integer, String&gt; m,因为您有权访问的 map 是在调用该方法时传入的同一个实例对象。

编辑:为什么m = null; 表现为按值传递,而m.clear() 表现为按引用传递?

当您将值 null“分配”到 m 时,您正在将引用从先前的实例对象 map 更改为新的内存位置 null

当您在实例对象m 上调用.clear() 方法时,您正在对位于map 引用的内存位置的同一对象调用该方法,因此您修改了map 对象。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-12-23
    • 2014-09-10
    • 2015-07-19
    • 2013-12-02
    • 2012-03-12
    • 2013-09-15
    • 1970-01-01
    • 2012-03-13
    相关资源
    最近更新 更多