理解Java中的“按值传递”和“按引用传递”
2024-11-24 14:25:55
当谈到方法参数时,java 编程中最容易被误解的主题之一是“按值传递”和“按引用传递”之间的区别。在这篇博文中,我们将深入探讨这些概念,包括 java 如何实际处理方法参数,并提供说明性代码示例来阐明幕后发生的事情。
“按值传递”和“按引用传递”是什么意思? 按值传递:在“按值传递”中,方法接收传递给它的参数的实际值的副本。对方法内参数所做的任何修改都不会影响原始参数。
通过参考传递:在“按引用传递”中,方法接收对参数实际内存位置的引用(或地址)。对参数的修改直接影响原始对象,因为该方法在同一内存上操作。
java 如何处理方法参数?在java中,所有参数都是按值传递的。但是,此语句可能会产生误导,因为根据参数是基本类型还是对象引用,按值传递的内容会有所不同。
立即学习“Java免费学习笔记(深入)”;
- 原始类型:值本身被复制并传递给方法。
- 对象(非基元):复制对象的引用并将其传递给方法。虽然引用本身是一个副本,但它仍然指向内存中的同一个对象。
这种区别可能会造成混乱,导致一些开发人员错误地认为 java 支持“按引用传递”。让我们用代码示例来分解它。
按值传递:原始类型当您将基本类型传递给方法时,java 会创建实际值的副本。方法内参数的更改不会影响原始变量。
public class passbyvaluedemo { public static void main(string[] args) { int num = 10; system.out.println("before method call: " + num); // output: 10 modifyprimitive(num); system.out.println("after method call: " + num); // output: 10 } public static void modifyprimitive(int n) { n = 20; // changes the copy, not the original system.out.println("inside method: " + n); // output: 20 } }
说明:
• num 的值被复制并传递给modifyprimitive 方法。 • 在方法内部,对本地副本(n)进行了更改,但主方法中的 num 保持不变。
按值传递:对象引用对于对象来说,引用(内存地址)是按值传递的。这意味着该方法对引用指向的同一个对象进行操作,但引用本身是一个副本。让我们来说明一下:
示例1:修改对象状态
class person { string name; person(string name) { this.name = name; } } public class passbyvalueobject { public static void main(string[] args) { person person = new person("alice"); system.out.println("before method call: " + person.name); // output: alice modifyobject(person); system.out.println("after method call: " + person.name); // output: bob } public static void modifyobject(person p) { p.name = "bob"; // modifies the same object system.out.println("inside method: " + p.name); // output: bob } }
说明:
• 复制对 person 对象的引用并将其传递给modifyobject 方法。 • 原始引用和复制引用都指向内存中的同一对象,因此对象状态的更改在方法外部可见。
示例 2:重新分配对象引用
现在让我们看看如果您尝试在方法内重新分配引用本身会发生什么。
public class passbyvaluereassign { public static void main(string[] args) { person person = new person("alice"); system.out.println("before method call: " + person.name); // output: alice reassignobject(person); system.out.println("after method call: " + person.name); // output: alice } public static void reassignobject(person p) { p = new person("charlie"); // reassigns the local copy of the reference system.out.println("inside method: " + p.name); // output: charlie } }
说明:
• 引用人员被复制并传递给 reassignobject 方法。 • 在方法内部,本地副本 (p) 被重新分配以指向新对象 (new person("charlie")),但这不会影响 main 方法中的原始引用。 • 主静态中的原始人物引用指向“alice”对象。
揭秘:内存中发生了什么?原始类型:
• 该值直接存储在与变量关联的内存位置。 • 当传递给方法时,该值将被复制到参数的新内存位置。
对象引用:
• 对象的引用(内存地址)存储在变量中。 • 当传递给方法时,引用会被复制,因此原始引用和复制的引用都指向堆内存中的同一个对象。
行为可视化示例:对象引用
Person person = new Person("Alice"); // Memory layout // Stack (local variables): // person -> address: 0x1234 // Heap (objects): // 0x1234 -> Person{name="Alice"}
当传递给方法时: • 创建一个新引用(例如 p),它也指向 0x1234。
要点- java 始终是“按值传递”。 • 对于基元:复制值本身。 • 对于对象:引用被复制,但两个引用都指向同一个对象。
- 修改对象的状态会影响原始对象,因为方法操作于同一个对象。
- 在方法内重新分配引用不会影响方法外的原始引用。
通过理解这些细微差别,您将能够更好地推理 java 方法调用并避免程序中的常见陷阱。
以上就是理解Java中的“按值传递”和“按引用传递”的详细内容,更多请关注图灵教育其它相关文章!