Java方法调用修改对象疑问:为何自定义对象可改而Integer不行?
为什么Java中Integer对象无法被方法修改,但自定义对象可以?
这是Java里最容易混淆的参数传递问题之一,我来一步步帮你理清楚:
首先先看你给出的示例代码:
// My Integer Object class MyInteger { Integer val; } // Change Java Object public void test1() { Integer intval; // Integer object intval = 123; setInteger(intval); // THIS DOESN'T WORK TTY.putR("Integer Object=" + intval); } // Change My Object public void test2() { MyInteger myInt; // MyInteger object myInt = new MyInteger(); myInt.val = 456; setMyInteger(myInt); // THIS WORKS! TTY.putR("MyIntegerObject=" + myInt.val); } // Set an Integer object public void setInteger(Integer val) { val = 888; } // Set a MyInteger object public void setMyInteger(MyInteger myint) { myint.val = 999; }
核心误区:Java是值传递,不是引用传递
很多人会误以为Java传递对象是“引用传递”,但准确来说,Java的所有参数传递都是值传递——当你传递对象时,传递的是「对象引用的副本」,而不是引用本身,更不是对象本身。这是理解这个问题的关键。
为什么test1里的Integer没被修改?
- 当你调用
setInteger(intval)时,intval指向的是值为123的Integer对象,方法会把这个引用的副本传给参数val。此时,intval和val是两个独立的引用,但都指向同一个123的Integer对象。 - 然后你执行
val = 888;——这里要注意:Integer是不可变类,它的内部值一旦创建就不能被修改。这句代码其实是创建了一个新的、值为888的Integer对象,然后让方法里的val引用指向这个新对象。 - 但原引用
intval还是指向原来的123对象,方法结束后,副本val被销毁,外部完全看不到这个变化,所以打印出来还是123。
为什么test2里的MyInteger能被修改?
- 调用
setMyInteger(myInt)时,同样传递的是myInt引用的副本,这个副本和原引用myInt都指向同一个MyInteger对象(里面的val是456)。 - 执行
myint.val = 999;时,你并没有修改引用本身,而是修改了引用指向的对象的内部属性。因为原引用和副本指向的是同一个对象,所以外部的myInt.val自然会看到这个修改后的结果。
总结一下
- 如果你的方法只是修改参数引用本身(让它指向新对象),那么外部的原引用不会受到任何影响——因为你改的是副本。
- 如果你的方法修改的是引用指向的对象的内部状态,并且这个对象是可变的(比如你的MyInteger),那么外部会看到变化——因为原引用和副本都指向同一个对象。
- 像Integer、String这类不可变类,你根本无法修改它们的内部状态,所有看似“修改”的操作都是生成新对象,所以永远无法通过方法改变原引用指向的对象。
内容的提问来源于stack exchange,提问作者DontPanic
相关产品推荐
相关产品推荐

